﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если НЕ МобильныйАвтономныйСервер Тогда

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область ПрограммныйИнтерфейс

#Область ДляВызоваИзДругихПодсистем

// СтандартныеПодсистемы.ГрупповоеИзменениеОбъектов

// Возвращает реквизиты объекта, которые разрешается редактировать
// с помощью обработки группового изменения реквизитов.
//
// Возвращаемое значение:
//  Массив из Строка
//
Функция РеквизитыРедактируемыеВГрупповойОбработке() Экспорт
	
	РедактируемыеРеквизиты = Новый Массив;
	
	Возврат РедактируемыеРеквизиты;
	
КонецФункции

// Конец СтандартныеПодсистемы.ГрупповоеИзменениеОбъектов

// ТехнологияСервиса.ВыгрузкаЗагрузкаДанных

// Возвращает реквизиты справочника, которые образуют естественный ключ для элементов справочника.
//
// Возвращаемое значение:
//  Массив из Строка - массив имен реквизитов, образующих естественный ключ.
//
Функция ПоляЕстественногоКлюча() Экспорт
	
	Результат = Новый Массив;
	Результат.Добавить("ПолноеИмя");
	
	Возврат Результат;
	
КонецФункции

// Конец ТехнологияСервиса.ВыгрузкаЗагрузкаДанных

#КонецОбласти

#КонецОбласти

#КонецЕсли

#Область ОбработчикиСобытий

Процедура ОбработкаПолученияПолейПредставления(Поля, СтандартнаяОбработка) Экспорт
	
	СтандартнаяОбработка = Ложь;
	
	Поля.Добавить("Ссылка");
	Поля.Добавить("Наименование");
	
КонецПроцедуры

Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка) Экспорт
	
	Если Не ЗначениеЗаполнено(Данные.Ссылка) Тогда
		Возврат;
	КонецЕсли;
	
	СтандартнаяОбработка = Ложь;
	
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
	Представление = СтандартныеПодсистемыПовтИсп.ПредставлениеИдентификатораОбъектаМетаданных(Данные.Ссылка);
#Иначе
	Представление = СтандартныеПодсистемыКлиентПовтИсп.ПредставлениеИдентификатораОбъектаМетаданных(Данные.Ссылка);
#КонецЕсли
	
КонецПроцедуры

#КонецОбласти

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область СлужебныйПрограммныйИнтерфейс

// Параметры:
//  ИмяПараметра - Строка
//  УстановленныеПараметры - Массив из Строка
//
// Возвращаемое значение:
//  Булево
//
Функция ВсеПараметрыСеансаУстановлены(ИменаПараметровСеанса, УстановленныеПараметры) Экспорт
	
	Если ИменаПараметровСеанса.Найти("ОбновлениеСправочниковИдентификаторов") = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Результат = Новый Структура;
	Результат.Вставить("ИдентификаторыОбъектовМетаданных", Ложь);
	Результат.Вставить("ИдентификаторыОбъектовРасширений", Ложь);
	
	ПараметрыСеанса.ОбновлениеСправочниковИдентификаторов = Новый ФиксированнаяСтруктура(Результат);
	
	УстановленныеПараметры.Добавить("ОбновлениеСправочниковИдентификаторов");
	Возврат ИменаПараметровСеанса.Количество() = 1;
	
КонецФункции

// Только для внутреннего использования.
Процедура ПроверкаИспользования(ОбъектыРасширений = Ложь) Экспорт
	
	Если СтандартныеПодсистемыПовтИсп.ОтключитьИдентификаторыОбъектовМетаданных() Тогда
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Справочник ""%1"" не используется.'"), НазваниеСправочника(ОбъектыРасширений));
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Если ОбъектыРасширений И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		ТекстОшибки = ОписаниеОшибкиИдентификаторыОбъектовРасширенийНедоступныВНеразделенномРежиме();
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	
	Если ПланыОбмена.ГлавныйУзел() = Неопределено
	   И ЗначениеЗаполнено(ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени("Константа.ГлавныйУзел").Получить()) Тогда
		
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Справочник ""%1"" не может использоваться
			           |в информационной базе с неподтвержденной отменой главного узла.
			           |
			           |Для восстановления связи с главным узлом запустите 1С:Предприятие и
			           |нажмите кнопку Восстановить или программно установите главный узел,
			           |сохраненный в константе Главный узел.
			           |
			           |Для подтверждения отмены связи с главным узлом запустите 1С:Предприятие и
			           |нажмите кнопку Отключить или программно очистите константу Главный узел.'"),
			НазваниеСправочника(ОбъектыРасширений));
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
КонецПроцедуры

// Возвращает Истина, если проверка, обновление и замена дублей завершена.
//
// Параметры:
//  Обновить - Булево - если передать Истина, тогда данные будут обновлены,
//             если возможно. Если невозможно, тогда будет вызвано исключение.
//             Если передать Ложь, тогда будет возвращено состояние данных.
//  
//  ОбъектыРасширений - Булево
//
// Возвращаемое значение:
//  Булево
//
Функция ДанныеОбновлены(Обновить = Ложь, ОбъектыРасширений = Ложь) Экспорт
	
	Попытка
		Обновлен = СтандартныеПодсистемыСервер.ПараметрРаботыПрограммы(
			"СтандартныеПодсистемы.БазоваяФункциональность.ИдентификаторыОбъектовМетаданных");
	Исключение
		Если Обновить Тогда
			ВызватьИсключение;
		КонецЕсли;
		Возврат Ложь;
	КонецПопытки;
	
	Если Обновлен = Неопределено Тогда
		Если Обновить Тогда
			ОбновитьДанныеСправочника();
		Иначе
			Возврат Ложь;
		КонецЕсли;
	КонецЕсли;
	
	Если ОбъектыРасширений
	   И ЗначениеЗаполнено(ПараметрыСеанса.ПодключенныеРасширения) Тогда
		
		Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
			Если Обновить Тогда
				ТекстОшибки = ОписаниеОшибкиИдентификаторыОбъектовРасширенийНедоступныВНеразделенномРежиме();
				ВызватьИсключение ТекстОшибки;
			Иначе
				Возврат Ложь;
			КонецЕсли;
		КонецЕсли;
		
		Если Не Справочники.ИдентификаторыОбъектовРасширений.ИдентификаторыОбъектовТекущейВерсииРасширенийЗаполнены() Тогда
			Справочники.ИдентификаторыОбъектовРасширений.ОбновитьДанныеСправочника();
		КонецЕсли;
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

// Только для внутреннего использования.
//
// Параметры:
//  Объекты - Массив из СправочникОбъект.ИдентификаторыОбъектовМетаданных
//
Процедура ЗагрузитьДанныеВПодчиненныйУзел(Объекты) Экспорт
	
	Если ОбщегоНазначения.РазделениеВключено() Тогда
		// В модели сервиса не поддерживается.
		Возврат;
	КонецЕсли;
	
	Если Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
		Возврат;
	КонецЕсли;
	
	ПроверкаИспользования();
	СтандартныеПодсистемыСервер.ПроверитьДинамическоеОбновлениеВерсииПрограммы();
	
	Блокировка = Новый БлокировкаДанных;
	Блокировка.Добавить("Справочник.ИдентификаторыОбъектовМетаданных");
	
	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		
		// Подготовка исходной таблицы с учетом переименования для поиска дублей.
		Выгрузка = ВыгрузкаВсехИдентификаторов();
		Выгрузка.Колонки.Добавить("ДубльОбновлен", Новый ОписаниеТипов("Булево"));
		Выгрузка.Колонки.Добавить("ПолноеИмяНижнийРегистр", Новый ОписаниеТипов("Строка"));
		
		// Отбор только тех из загружаемых объектов, которые отличаются от существующих.
		ТаблицаЗагружаемых = Новый ТаблицаЗначений;
		ТаблицаЗагружаемых.Колонки.Добавить("Объект");
		ТаблицаЗагружаемых.Колонки.Добавить("Ссылка");
		ТаблицаЗагружаемых.Колонки.Добавить("ОбъектМетаданныхПоКлючу");
		ТаблицаЗагружаемых.Колонки.Добавить("ОбъектМетаданныхПоПолномуИмени");
		ТаблицаЗагружаемых.Колонки.Добавить("Совпадает", Новый ОписаниеТипов("Булево"));
		
		Для каждого Объект Из Объекты Цикл
			СвойстваЗагружаемого = ТаблицаЗагружаемых.Добавить();
			СвойстваЗагружаемого.Объект = Объект;
			
			Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
				СвойстваЗагружаемого.Ссылка = Объект.Ссылка;
			Иначе
				СвойстваЗагружаемого.Ссылка = Объект.ПолучитьСсылкуНового();
				Если Не ЗначениеЗаполнено(СвойстваЗагружаемого.Ссылка) Тогда
					ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
						НСтр("ru = 'Ошибка загрузки идентификаторов объектов метаданных.
						           |Невозможно загрузить новый элемент у которого не указана ссылка нового:
						           |""%1"".'"),
						Объект.ПолноеИмя);
					ВызватьИсключение ТекстОшибки;
				КонецЕсли;
			КонецЕсли;
			
			// Предварительная обработка.
			
			Если Не ЭтоКоллекция(СвойстваЗагружаемого.Ссылка) Тогда
				СвойстваЗагружаемого.ОбъектМетаданныхПоКлючу = ОбъектМетаданныхПоКлючу(
					Объект.КлючОбъектаМетаданных.Получить(), "", "", "");
				
				СвойстваЗагружаемого.ОбъектМетаданныхПоПолномуИмени =
					МетаданныеНайтиПоПолномуИмени(Объект.ПолноеИмя);
				
				Если СвойстваЗагружаемого.ОбъектМетаданныхПоКлючу = Неопределено
				   И СвойстваЗагружаемого.ОбъектМетаданныхПоПолномуИмени = Неопределено
				   И Объект.ПометкаУдаления <> Истина Тогда
					// Если по какой-то причине загружаемый объект не найден в метаданных,
					// его следует пометить на удаление.
					Объект.ПометкаУдаления = Истина;
				КонецЕсли;
			КонецЕсли;
			
			Если Объект.ПометкаУдаления Тогда
				// Для помеченных на удаление недопустимо корректное полное имя,
				// поэтому для надежного обеспечения этого условия, процедура обновления
				// свойств помеченного дополнительно применяется перед загрузкой.
				ОбновитьСвойстваПомеченногоНаУдаление(Объект);
			КонецЕсли;
			
			Свойства = Выгрузка.Найти(СвойстваЗагружаемого.Ссылка, "Ссылка");
			Если Свойства <> Неопределено
			   И Свойства.Наименование              = Объект.Наименование
			   И Свойства.Родитель                  = Объект.Родитель
			   И Свойства.ПорядокКоллекции          = Объект.ПорядокКоллекции
			   И Свойства.Имя                       = Объект.Имя
			   И Свойства.Синоним                   = Объект.Синоним
			   И Свойства.ПолноеИмя                 = Объект.ПолноеИмя
			   И Свойства.ПолныйСиноним             = Объект.ПолныйСиноним
			   И Свойства.БезДанных                 = Объект.БезДанных
			   И Свойства.ЗначениеПустойСсылки      = Объект.ЗначениеПустойСсылки
			   И Свойства.ИмяПредопределенныхДанных = Объект.ИмяПредопределенныхДанных
			   И Свойства.ПометкаУдаления           = Объект.ПометкаУдаления
			   И КлючиОбъектовМетаданныхСовпадают(Свойства, Объект) Тогда
				
				СвойстваЗагружаемого.Совпадает = Истина;
			КонецЕсли;
			
			Если Свойства <> Неопределено Тогда
				Выгрузка.Удалить(Свойства); // Загружаемые не нужно переименовывать.
			КонецЕсли;
		КонецЦикла;
		ТаблицаЗагружаемых.Индексы.Добавить("Ссылка");
		
		// Переименование существующих элементов (без загружаемых) для поиска дублей.
		
		ПереименоватьПолныеИмена(Выгрузка);
		Для каждого Строка Из Выгрузка Цикл
			Строка.ПолноеИмяНижнийРегистр = НРег(Строка.ПолноеИмя);
		КонецЦикла;
		Выгрузка.Индексы.Добавить("КлючОбъектаМетаданных");
		Выгрузка.Индексы.Добавить("ПолноеИмяНижнийРегистр");
		
		// Подготовка загружаемых объектов и дублей в существующих.
		
		ОбъектыДляЗаписи = Новый Массив; // Массив из СправочникОбъект.ИдентификаторыОбъектовМетаданных -
		ПолныеИменаЗагружаемых = Новый Соответствие;
		КлючиЗагружаемых = Новый Соответствие;
		
		Для каждого СвойстваЗагружаемого Из ТаблицаЗагружаемых Цикл
			Объект = СвойстваЗагружаемого.Объект; // СправочникОбъект.ИдентификаторыОбъектовМетаданных
			Ссылка = СвойстваЗагружаемого.Ссылка;
			
			Если СвойстваЗагружаемого.Совпадает Тогда
				Продолжить; // Точно совпадающие объекты не требуется загружать.
			КонецЕсли;
			
			Если ЭтоКоллекция(Ссылка) Тогда
				ОбъектыДляЗаписи.Добавить(Объект);
				Продолжить;
			КонецЕсли;
			
			// Проверка отсутствия дублей среди загружаемых элементов.
			
			Если ПолныеИменаЗагружаемых.Получить(НРег(Объект.ПолноеИмя)) <> Неопределено Тогда
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка загрузки идентификаторов объектов метаданных.
					           |Невозможно загрузить два элемента у которых совпадает полное имя:
					           |""%1"".'"),
					Объект.ПолноеИмя);
				ВызватьИсключение ТекстОшибки;
			КонецЕсли;
			ПолныеИменаЗагружаемых.Вставить(НРег(Объект.ПолноеИмя));
			
			КлючОбъектаМетаданных = Объект.КлючОбъектаМетаданных.Получить();
			Если ТипЗнч(КлючОбъектаМетаданных) = Тип("Тип")
			   И КлючОбъектаМетаданных <> Тип("Неопределено") Тогда
				
				Если КлючиЗагружаемых.Получить(КлючОбъектаМетаданных) <> Неопределено Тогда
					ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
						НСтр("ru = 'Ошибка загрузки идентификаторов объектов метаданных.
						           |Невозможно загрузить два элемента у которых совпадает ключ объекта метаданных:
						           |""%1"".'"),
						Строка(КлючОбъектаМетаданных));
					ВызватьИсключение ТекстОшибки;
				КонецЕсли;
				КлючиЗагружаемых.Вставить(КлючОбъектаМетаданных);
				
				Если СвойстваЗагружаемого.ОбъектМетаданныхПоКлючу <> СвойстваЗагружаемого.ОбъектМетаданныхПоПолномуИмени Тогда
					ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
						НСтр("ru = 'Ошибка загрузки идентификаторов объектов метаданных.
						           |Невозможно загрузить элемент у которого ключ объекта метаданных
						           |""%1"" не соответствует полному имени ""%2"".'"),
						Строка(КлючОбъектаМетаданных), Объект.ПолноеИмя);
					ВызватьИсключение ТекстОшибки;
				КонецЕсли;
				
				Если Не Объект.ПометкаУдаления Тогда
					// Определение дублей среди существующих объектов метаданных по ключу.
					Отбор = Новый Структура("КлючОбъектаМетаданных", КлючОбъектаМетаданных);
					ОпределитьДублиПриЗагрузкеВПодчиненныйУзел(Выгрузка, Отбор, Объект, Ссылка, ТаблицаЗагружаемых);
				КонецЕсли;
			КонецЕсли;
			
			Если Не Объект.ПометкаУдаления Тогда
				// Определение дублей среди существующих объектов метаданных по полному имени.
				Отбор = Новый Структура("ПолноеИмяНижнийРегистр", НРег(Объект.ПолноеИмя));
				ОпределитьДублиПриЗагрузкеВПодчиненныйУзел(Выгрузка, Отбор, Объект, Ссылка, ТаблицаЗагружаемых);
			КонецЕсли;
			
			ОбъектыДляЗаписи.Добавить(Объект);
		КонецЦикла;
		
		// Обновление дублей.
		Строки = Выгрузка.НайтиСтроки(Новый Структура("ДубльОбновлен", Истина));
		Для каждого Свойства Из Строки Цикл
			ОбъектДубля = Свойства.Ссылка.ПолучитьОбъект();
			ЗаполнитьЗначенияСвойств(ОбъектДубля, Свойства);
			ОбъектДубля.КлючОбъектаМетаданных = Новый ХранилищеЗначения(Свойства.КлючОбъектаМетаданных);
			ОбъектДубля.ОбменДанными.Загрузка = Истина;
			ОбъектДубля.Записать();
		КонецЦикла;
		
		ПодготовитьСписокНовыхПодсистемВПодчиненномУзле(ОбъектыДляЗаписи);
		
		// Загрузка объектов.
		Для каждого Объект Из ОбъектыДляЗаписи Цикл
			Объект.ОбменДанными.Загрузка = Истина;
			Объект.Записать();
		КонецЦикла;
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

// Возвращает ссылки на объект метаданных, найденный по полному имени удаленного объекта метаданных.
// Используется когда требуется сделать замену старой ссылки на новую или очистить ее.
//
// Параметры:
//  ПолноеИмяУдаленного - Строка - например, "Роль.ЧтениеБазовойНСИ".
//
// Возвращаемое значение:
//  Массив - со значениями:
//   * Значение - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//              - СправочникСсылка.ИдентификаторыОбъектовРасширений - найденная ссылка.
// 
Функция ИдентификаторУдаленногоОбъектаМетаданных(ПолноеИмяУдаленного) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ИдентификаторыОбъектовМетаданных.Ссылка КАК Ссылка,
	|	ИдентификаторыОбъектовМетаданных.ПолноеИмя КАК ПолноеИмя
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных
	|ГДЕ
	|	ИдентификаторыОбъектовМетаданных.ПометкаУдаления
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ИдентификаторыОбъектовРасширений.Ссылка,
	|	ИдентификаторыОбъектовРасширений.ПолноеИмя
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовРасширений КАК ИдентификаторыОбъектовРасширений
	|ГДЕ
	|	ИдентификаторыОбъектовРасширений.ПометкаУдаления";
	
	Выборка = Запрос.Выполнить().Выбрать();
	
	НайденныеСсылки = Новый Массив;
	Пока Выборка.Следующий() Цикл
		Если Не СтрНачинаетсяС(Выборка.ПолноеИмя, "? ") Тогда
			Продолжить;
		КонецЕсли;
		ТекущееПолноеИмяУдаленного = ПолноеИмяУдаленного(Выборка.ПолноеИмя);
		Если ВРег(ТекущееПолноеИмяУдаленного) = ВРег(ПолноеИмяУдаленного) Тогда
			НайденныеСсылки.Добавить(Выборка.Ссылка);
		КонецЕсли;
	КонецЦикла;
	
	Возврат НайденныеСсылки;
	
КонецФункции

// Параметры:
//  Идентификаторы - Массив - со значениями:
//                     * Значение - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//                                - СправочникСсылка.ИдентификаторыОбъектовРасширений - идентификаторы
//                                    объектов метаданных конфигурации или расширений конфигурации.
// Возвращаемое значение:
//  Соответствие из КлючИЗначение:
//   * Ключ     - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//              - СправочникСсылка.ИдентификаторыОбъектовРасширений
//   * Значение - Строка - полное имя объекта метаданных без "? ".
//
Функция ПолныеИменаОбъектовМетаданныхВключаяУдаленные(Идентификаторы) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Идентификаторы", Идентификаторы);
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ИдентификаторыОбъектовМетаданных.Ссылка КАК Ссылка,
	|	ИдентификаторыОбъектовМетаданных.ПолноеИмя КАК ПолноеИмя
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных
	|ГДЕ
	|	ИдентификаторыОбъектовМетаданных.Ссылка В(&Идентификаторы)
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ИдентификаторыОбъектовРасширений.Ссылка,
	|	ИдентификаторыОбъектовРасширений.ПолноеИмя
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовРасширений КАК ИдентификаторыОбъектовРасширений
	|ГДЕ
	|	ИдентификаторыОбъектовРасширений.Ссылка В(&Идентификаторы)";
	
	Результат = Новый Соответствие;
	
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Если СтрНачинаетсяС(Выборка.ПолноеИмя, "? ") Тогда
			Результат.Вставить(Выборка.Ссылка, ПолноеИмяУдаленного(Выборка.ПолноеИмя));
		Иначе
			Результат.Вставить(Выборка.Ссылка, Выборка.ПолноеИмя);
		КонецЕсли;
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Возвращаемое значение:
//  Массив из Строка - имена коллекций объектов метаданных, которые поддерживаются в справочнике.
//
Функция ДопустимыеКоллекции() Экспорт
	
	СвойстваКоллекций = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных();
	
	Возврат СвойстваКоллекций.ВыгрузитьКолонку("Имя");
	
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Процедура обновляет данные справочника по метаданным конфигурации.
//
// Параметры:
//  ЕстьИзменения  - Булево - возвращаемое значение. В этот параметр возвращается
//                   значение Истина, если производилась запись, иначе не изменяется.
//
//  ЕстьУдаленные  - Булево - возвращаемое значение. В этот параметр возвращается
//                   значение Истина, если хотя бы один элемент справочника был помечен
//                   на удаление, иначе не изменяется.
//
//  ТолькоПроверка - Булево - не производить никаких изменений, а лишь выполнить
//                   установку флажков ЕстьИзменения, ЕстьУдаленные.
//
Процедура ОбновитьДанныеСправочника(ЕстьИзменения = Ложь, ЕстьУдаленные = Ложь, ТолькоПроверка = Ложь) Экспорт
	
	ВыполнитьОбновлениеДанных(ЕстьИзменения, ЕстьУдаленные, ТолькоПроверка);
	
КонецПроцедуры

// Требуется, чтобы выгрузить все идентификаторы объектов метаданных конфигурации
// в подчиненные узлы РИБ, если ранее справочник не был включен в РИБ.
// Также может использоваться для ремонта данных справочника в РИБ-узлах.
//
Процедура ЗарегистрироватьПолноеИзменениеДляПодчиненныхУзловРИБ() Экспорт
	
	ПроверкаИспользования();
	
	Если ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ()
	 Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		Возврат;
	КонецЕсли;
	
	МетаданныеСправочника = Метаданные.Справочники.ИдентификаторыОбъектовМетаданных;
	
	УзлыРИБ = Новый Массив;
	Для каждого ПланОбмена Из Метаданные.ПланыОбмена Цикл
		Если ПланОбмена.РаспределеннаяИнформационнаяБаза
		   И ПланОбмена.Состав.Содержит(МетаданныеСправочника)Тогда
		
			ПланОбменаМенеджер = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПланОбмена.ПолноеИмя());
			Выборка = ПланОбменаМенеджер.Выбрать();
			Пока Выборка.Следующий() Цикл
				Если Выборка.Ссылка <> ПланОбменаМенеджер.ЭтотУзел() Тогда
					УзлыРИБ.Добавить(Выборка.Ссылка);
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	
	Если УзлыРИБ.Количество() > 0 Тогда
		ПланыОбмена.ЗарегистрироватьИзменения(УзлыРИБ, МетаданныеСправочника);
	КонецЕсли;
	
КонецПроцедуры

// Процедура обновляет данные справочника по метаданным конфигурации.
//
// Параметры:
//  ЕстьИзменения - Булево - возвращаемое значение. В этот параметр возвращается
//                  значение Истина, если производилась запись, иначе не изменяется.
//
//  ЕстьУдаленные - Булево - возвращаемое значение. В этот параметр возвращается
//                  значение Истина, если хотя бы один элемент справочника был помечен
//                  на удаление, иначе не изменяется.
//
//  ТолькоПроверка - Булево - не производить никаких изменений, а выполнить только установку
//                   параметров ЕстьИзменения, ЕстьУдаленные, ЕстьКритичныеИзменения, СписокКритичныхИзменений.
//
//  ЕстьКритичныеИзменения - Булево - возвращаемое значение. В этот параметр возвращается
//                  значение Истина, если найдены критичные изменения, иначе не изменяется.
//                    Критичные изменения (только для непомеченных на удаление):  
//                    изменении реквизита ПолноеИмя или добавление нового элемента справочника.
//                  В общем случае критичные изменения требуют монопольный режим.
//
//  СписокКритичныхИзменений - Строка - возвращаемое значение. Содержит полные имена
//                  объектов метаданных, которые добавлены или требуется добавить,
//                  а также объектов метаданных, полные имена которых изменены или требуется изменить.
//
//  ОбъектыРасширений - Булево
//
Процедура ВыполнитьОбновлениеДанных(ЕстьИзменения, ЕстьУдаленные, ТолькоПроверка,
			ЕстьКритичныеИзменения = Ложь, СписокКритичныхИзменений = "", ОбъектыРасширений = Ложь) Экспорт
	
	Если ОбъектыРасширений
	   И ЗначениеЗаполнено(ПараметрыСеанса.ПодключенныеРасширения)
	   И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		
		ВызватьИсключениеПоОшибке(Истина,
			ОписаниеОшибкиИдентификаторыОбъектовРасширенийНедоступныВНеразделенномРежиме());
	КонецЕсли;
	
	ПроверкаИспользования(ОбъектыРасширений);
	
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);
	
	ЕстьТекущиеИзменения = Ложь;
	Если Не ОбъектыРасширений Тогда
		ЗаменитьДублиПодчиненногоУзлаНайденныеПриЗагрузке(ТолькоПроверка, ЕстьТекущиеИзменения);
	КонецЕсли;
	
	ОбновитьДанные(ЕстьТекущиеИзменения, ЕстьУдаленные, ТолькоПроверка,
		ЕстьКритичныеИзменения, СписокКритичныхИзменений, ОбъектыРасширений);
	
	Если ЕстьТекущиеИзменения Тогда
		ЕстьИзменения = Истина;
	КонецЕсли;
	
	Если Не ОбъектыРасширений
	   И Не СтандартныеПодсистемыСервер.ВерсияПрограммыОбновленаДинамически() Тогда
		
		СтандартныеПодсистемыСервер.ОбновитьПараметрРаботыПрограммы(
			"СтандартныеПодсистемы.БазоваяФункциональность.ИдентификаторыОбъектовМетаданных", Истина);
	КонецЕсли;
	
	Если Не ТолькоПроверка И Не ТранзакцияАктивна() Тогда
		ВыполненоОбновление = Новый Структура(ПараметрыСеанса.ОбновлениеСправочниковИдентификаторов);
		Если ОбъектыРасширений Тогда
			ВыполненоОбновление.ИдентификаторыОбъектовРасширений = Истина;
		Иначе
			ВыполненоОбновление.ИдентификаторыОбъектовМетаданных = Истина;
		КонецЕсли;
		ПараметрыСеанса.ОбновлениеСправочниковИдентификаторов = Новый ФиксированнаяСтруктура(ВыполненоОбновление);
	КонецЕсли;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Реализация процедур, объявленных в других модулях.

// См. ОбщегоНазначения.ИдентификаторОбъектаМетаданных.
Функция ИдентификаторОбъектаМетаданных(ОписаниеОбъектаМетаданных, ВызыватьИсключение) Экспорт
	
	ТипОписанияОбъектаМетаданных = ТипЗнч(ОписаниеОбъектаМетаданных);
	Если ТипОписанияОбъектаМетаданных = Тип("Тип") Тогда
		
		ОбъектМетаданных = Метаданные.НайтиПоТипу(ОписаниеОбъектаМетаданных);
		
		Если ОбъектМетаданных <> Неопределено Тогда
			ПолноеИмяОбъектаМетаданных = ОбъектМетаданных.ПолноеИмя();
			
		ИначеЕсли Не ВызыватьИсключение Тогда
			Возврат Null;
		Иначе
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Некорректное значение параметра %1 в функции %2.
				           |Указан несуществующий объект метаданных: ""%3"".'"),
				"ОписаниеОбъектаМетаданных",
				"ОбщегоНазначения.ИдентификаторОбъектаМетаданных",
				ОписаниеОбъектаМетаданных);
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
		
	ИначеЕсли ТипОписанияОбъектаМетаданных = Тип("Строка") Тогда
		ПолноеИмяОбъектаМетаданных = ОписаниеОбъектаМетаданных;
		
	ИначеЕсли ТипОписанияОбъектаМетаданных = Тип("ОбъектМетаданных") Тогда
		ПолноеИмяОбъектаМетаданных = ОписаниеОбъектаМетаданных.ПолноеИмя();
		
	ИначеЕсли Не ВызыватьИсключение Тогда
		Возврат Null;
	Иначе
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Некорректный тип параметра %1 в функции %2:
			           |""%3"".'"),
			"ОписаниеОбъектаМетаданных",
			"ОбщегоНазначения.ИдентификаторОбъектаМетаданных",
			ТипОписанияОбъектаМетаданных);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Массив = Новый Массив;
	Массив.Добавить(ПолноеИмяОбъектаМетаданных);
	
	Идентификаторы = ИдентификаторыОбъектовМетаданных(Массив, ВызыватьИсключение, Истина);
	Идентификатор = Идентификаторы.Получить(ПолноеИмяОбъектаМетаданных);
	Если Идентификатор = Неопределено Тогда
		Возврат Null;
	КонецЕсли;
	
	Возврат Идентификатор;
	
КонецФункции

// См. ОбщегоНазначения.ИдентификаторыОбъектовМетаданных.
Функция ИдентификаторыОбъектовМетаданных(ОписаниеОбъектовМетаданных, ВызыватьИсключение = Истина, ОдинЭлемент = Ложь) Экспорт
	
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);
	ИдентификаторыПоПолнымИменам = КэшИдентификаторов().ИдентификаторыПоПолнымИменам;
	УстановитьПривилегированныйРежим(Ложь);
	УстановитьОтключениеБезопасногоРежима(Ложь);
	
	Результат = Новый Соответствие;
	ПолныеИменаБезКэша = Новый Массив;
	Для Каждого ОписаниеОбъектаМетаданных Из ОписаниеОбъектовМетаданных Цикл
		
		ТипОписанияОбъектаМетаданных = ТипЗнч(ОписаниеОбъектаМетаданных);
		Если ТипОписанияОбъектаМетаданных = Тип("Тип") Тогда
		
			ОбъектМетаданных = Метаданные.НайтиПоТипу(ОписаниеОбъектаМетаданных);
			Если ОбъектМетаданных <> Неопределено Тогда
				ПолноеИмя = ОбъектМетаданных.ПолноеИмя();
			ИначеЕсли Не ВызыватьИсключение Тогда
				Продолжить;
			Иначе
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Некорректное значение параметра %1 функции %2:
					           |Указан несуществующий объект метаданных: ""%3"".'"),
					"ОписаниеОбъектовМетаданных",
					"ОбщегоНазначения.ИдентификаторыОбъектовМетаданных",
					ОписаниеОбъектаМетаданных);
				ВызватьИсключение ТекстОшибки;
			КонецЕсли;
			
		ИначеЕсли ТипОписанияОбъектаМетаданных = Тип("Строка") Тогда
			ПолноеИмя = ОписаниеОбъектаМетаданных;
			
		ИначеЕсли ТипОписанияОбъектаМетаданных = Тип("ОбъектМетаданных") Тогда
			ПолноеИмя = ОписаниеОбъектаМетаданных.ПолноеИмя();
			
		ИначеЕсли Не ВызыватьИсключение Тогда
			Продолжить;
		Иначе
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Некорректный тип параметра %1 функции %2:
				           |""%3"".'"),
				"ОписаниеОбъектовМетаданных",
				"ОбщегоНазначения.ИдентификаторыОбъектовМетаданных",
				ТипОписанияОбъектаМетаданных);
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
		Идентификатор = ИдентификаторыПоПолнымИменам.Получить(ПолноеИмя);
		
		Если Идентификатор = Неопределено Тогда
			ПолныеИменаБезКэша.Добавить(ПолноеИмя);
		Иначе
			Результат.Вставить(ПолноеИмя, Идентификатор);
		КонецЕсли;
	КонецЦикла;
	
	Если ПолныеИменаБезКэша.Количество() = 0 Тогда
		Возврат Результат;
	КонецЕсли;
	
	Идентификаторы = ИдентификаторыОбъектовМетаданныхСПопыткойПовтора(ПолныеИменаБезКэша,
		ВызыватьИсключение, ОдинЭлемент);
	
	Для Каждого КлючИЗначение Из Идентификаторы Цикл
		Результат.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
		ИдентификаторыПоПолнымИменам.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// См. ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору.
Функция ОбъектМетаданныхПоИдентификатору(Идентификатор, ВызыватьИсключение) Экспорт
	
	Идентификаторы = Новый Массив;
	Идентификаторы.Добавить(Идентификатор);
	
	ОбъектыМетаданных = ОбъектыМетаданныхПоИдентификаторам(Идентификаторы, ВызыватьИсключение);
	
	Если Идентификатор = Неопределено Тогда
		Возврат Null;
	КонецЕсли;
	
	Возврат ОбъектыМетаданных.Получить(Идентификатор);
	
КонецФункции

// См. ОбщегоНазначения.ОбъектыМетаданныхПоИдентификаторам.
Функция ОбъектыМетаданныхПоИдентификаторам(Идентификаторы, ВызыватьИсключение) Экспорт
	
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);
	ОписаниеОбъектовМетаданныхПоИдентификаторам = КэшИдентификаторов().ОписаниеОбъектовМетаданныхПоИдентификаторам;
	УстановитьПривилегированныйРежим(Ложь);
	УстановитьОтключениеБезопасногоРежима(Ложь);
	РолиПоКлючам = Неопределено;
	Результат = Новый Соответствие;
	ИдентификаторыБезКэша = Новый Массив;
	Для Каждого Идентификатор Из Идентификаторы Цикл
		Описание = ОписаниеОбъектовМетаданныхПоИдентификаторам.Получить(Идентификатор);
		
		Если Описание = Неопределено
		 Или ВызыватьИсключение
		   И Описание.Ключ = Неопределено Тогда
			
			ИдентификаторыБезКэша.Добавить(Идентификатор);
			
		ИначеЕсли Описание.Ключ = Неопределено Тогда
			Результат.Вставить(Идентификатор, Описание.Объект);
			
		ИначеЕсли ТипЗнч(Описание.Ключ) = Тип("Тип") Тогда
			Результат.Вставить(Идентификатор, Метаданные.НайтиПоТипу(Описание.Ключ));
		ИначеЕсли Описание.Ключ <> Описание.ПолноеИмя Тогда
			Если РолиПоКлючам = Неопределено Тогда
				РолиПоКлючам = СтандартныеПодсистемыПовтИсп.РолиПоКлючамОбъектовМетаданных();
			КонецЕсли;
			Результат.Вставить(Идентификатор, РолиПоКлючам.Получить(Описание.Ключ));
		Иначе
			Результат.Вставить(Идентификатор, ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(Описание.Ключ));
		КонецЕсли;
	КонецЦикла;
	
	Если ИдентификаторыБезКэша.Количество() = 0 Тогда
		Возврат Результат;
	КонецЕсли;
	
	ОбъектыМетаданныхПоИдентификаторам = ОбъектыМетаданныхПоИдентификаторамСПопыткойПовтора(ИдентификаторыБезКэша,
		ВызыватьИсключение);
	
	Для Каждого КлючИЗначение Из ОбъектыМетаданныхПоИдентификаторам Цикл
		ОписаниеОбъектаМетаданных = КлючИЗначение.Значение;
		Если ТипЗнч(ОписаниеОбъектаМетаданных) = Тип("Структура") Тогда
			Результат.Вставить(КлючИЗначение.Ключ, ОписаниеОбъектаМетаданных.Объект);
			ОписаниеОбъектаМетаданных.Объект = Неопределено;
		Иначе
			Результат.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
			ОписаниеОбъектаМетаданных = Новый Структура("Объект, Ключ, ПолноеИмя", КлючИЗначение.Значение)
		КонецЕсли;
		ОписаниеОбъектовМетаданныхПоИдентификаторам.Вставить(КлючИЗначение.Ключ, ОписаниеОбъектаМетаданных);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// См. ОбщегоНазначения.ДобавитьПереименование.
Процедура ДобавитьПереименование(Итог, ВерсияИБ, СтароеПолноеИмя, НовоеПолноеИмя, ИдентификаторБиблиотеки = "") Экспорт
	
	СтандартныеПодсистемыПовтИсп.ИдентификаторыОбъектовМетаданныхПроверкаИспользования();
	
	СтароеИмяКоллекции = ВРег(ИмяКоллекции(СтароеПолноеИмя));
	НовоеИмяКоллекции  = ВРег(ИмяКоллекции(НовоеПолноеИмя));
	
	ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Ошибка в процедуре %1 общего модуля %2.'"),
		"ПриДобавленииПереименованийОбъектовМетаданных",
		"ОбщегоНазначенияПереопределяемый");
	
	Если СтароеИмяКоллекции <> НовоеИмяКоллекции Тогда
		ТекстОшибки = ЗаголовокОшибки + Символы.ПС + Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Не совпадают имена типов переименованного объекта метаданных.
			           |Прежний тип: ""%1"",
			           |новый тип: ""%2"".'"),
			СтароеПолноеИмя,
			НовоеПолноеИмя);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Если Итог.КоллекцииБезКлюча[СтароеИмяКоллекции] = Неопределено Тогда
		
		СписокДопустимыхТипов = "";
		Для каждого КлючИЗначение Из Итог.КоллекцииБезКлюча Цикл
			СписокДопустимыхТипов = СписокДопустимыхТипов + КлючИЗначение.Значение + "," + Символы.ПС;
		КонецЦикла;
		СписокДопустимыхТипов = СокрП(СписокДопустимыхТипов);
		СписокДопустимыхТипов = ?(ЗначениеЗаполнено(СписокДопустимыхТипов),
			Лев(СписокДопустимыхТипов, СтрДлина(СписокДопустимыхТипов) - 1), "");
		
		ТекстОшибки = ЗаголовокОшибки + Символы.ПС + Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Для типа объекта метаданных ""%1"" не требуется описывать переименование,
			           |так как сведения об объектах метаданных этого типа обновляются автоматически.
			           |
			           |Описывать переименования требуется только для следующих типов:
			           |%2.'"),
			СтароеПолноеИмя,
			СписокДопустимыхТипов);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(ИдентификаторБиблиотеки) Тогда
		ИдентификаторБиблиотеки = Метаданные.Имя;
	КонецЕсли;
	
	ПорядокБиблиотеки = Итог.ПорядокБиблиотек[ИдентификаторБиблиотеки];
	Если ПорядокБиблиотеки = Неопределено Тогда
		ПорядокБиблиотеки = Итог.ПорядокБиблиотек.Количество();
		Итог.ПорядокБиблиотек.Вставить(ИдентификаторБиблиотеки, ПорядокБиблиотеки);
	КонецЕсли;
	
	ВерсияБиблиотеки = Итог.ВерсииБиблиотек[ИдентификаторБиблиотеки];
	Если ВерсияБиблиотеки = Неопределено Тогда
		ВерсияБиблиотеки = ОбновлениеИнформационнойБазыСлужебный.ВерсияИБ(ИдентификаторБиблиотеки);
		Итог.ВерсииБиблиотек.Вставить(ИдентификаторБиблиотеки, ВерсияБиблиотеки);
	КонецЕсли;
	
	Если ВерсияБиблиотеки = "0.0.0.0" Тогда
		// При начальном заполнении переименования не требуются.
		Возврат;
	КонецЕсли;
	
	Результат = ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ВерсияИБ, ВерсияБиблиотеки);
	Если Результат > 0 Тогда
		ЧастиВерсии = СтрРазделить(ВерсияИБ, ".");
		
		ТаблицаПереименования = Итог.Таблица; // см. ТаблицаПереименованияДляТекущейВерсии
		ОписаниеПереименования = ТаблицаПереименования.Добавить();
		ОписаниеПереименования.ПорядокБиблиотеки = ПорядокБиблиотеки;
		ОписаниеПереименования.ВерсияЧасть1      = Число(ЧастиВерсии[0]);
		ОписаниеПереименования.ВерсияЧасть2      = Число(ЧастиВерсии[1]);
		ОписаниеПереименования.ВерсияЧасть3      = Число(ЧастиВерсии[2]);
		ОписаниеПереименования.ВерсияЧасть4      = Число(ЧастиВерсии[3]);
		ОписаниеПереименования.СтароеПолноеИмя   = СтароеПолноеИмя;
		ОписаниеПереименования.НовоеПолноеИмя    = НовоеПолноеИмя;
		ОписаниеПереименования.ПорядокДобавления = ТаблицаПереименования.Индекс(ОписаниеПереименования);
	КонецЕсли;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Дополнительные процедуры и функции для вызова из других модулей.

// Только для внутреннего использования.
// ПолноеИмя в объекте должно быть уже установлено и корректно.
//
// Параметры:
//   Объект - СправочникОбъект.ИдентификаторыОбъектовМетаданных
//          - СправочникОбъект.ИдентификаторыОбъектовРасширений
//          - ДанныеФормыСтруктура:
//             * Ссылка - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//                      - СправочникСсылка.ИдентификаторыОбъектовРасширений
//
Процедура ОбновитьСвойстваИдентификатора(Объект) Экспорт
	
	Если ТипЗнч(Объект) <> Тип("ДанныеФормыСтруктура") Тогда
		ОбъектыРасширений = ЭтоОбъектРасширений(Объект);
	Иначе
		ОбъектыРасширений = ЭтоОбъектРасширений(Объект.Ссылка);
	КонецЕсли;
	
	Если ОбъектыРасширений
	   И Справочники.ИдентификаторыОбъектовРасширений.ОбъектРасширенияОтключен(Объект.Ссылка) Тогда
		Возврат;
	КонецЕсли;
	
	ПолноеИмя = Объект.ПолноеИмя;
	
	// Восстановление старых значений.
	Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
		СтарыеЗначения = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(
			Объект.Ссылка,
			"Наименование,
			|ПорядокКоллекции,
			|Имя,
			|ПолноеИмя,
			|Синоним,
			|ПолныйСиноним,
			|БезДанных,
			|ЗначениеПустойСсылки,
			|КлючОбъектаМетаданных");
		ЗаполнитьЗначенияСвойств(Объект, СтарыеЗначения);
	КонецЕсли;
	
	ОбъектМетаданных = МетаданныеНайтиПоПолномуИмени(ПолноеИмя);
	
	Если ОбъектМетаданных = Неопределено Тогда
		Объект.ПометкаУдаления       = Истина;
		Объект.Родитель              = ПустаяСсылкаСправочника(ОбъектыРасширений);
		Объект.Наименование          = ВставитьЗнакВопроса(Объект.Наименование);
		Объект.Имя                   = ВставитьЗнакВопроса(Объект.Имя);
		Объект.Синоним               = ВставитьЗнакВопроса(Объект.Синоним);
		Объект.ПолноеИмя             = ВставитьЗнакВопроса(Объект.ПолноеИмя);
		Объект.ПолныйСиноним         = ВставитьЗнакВопроса(Объект.ПолныйСиноним);
		Объект.ЗначениеПустойСсылки  = Неопределено;
		
		Если ОбъектыРасширений Тогда
			Объект.ИмяРасширения           = ВставитьЗнакВопроса(Объект.ИмяРасширения);
			Объект.ИдентификаторРасширения = ВставитьЗнакВопроса(Объект.ИдентификаторРасширения);
			Объект.ХешСуммаРасширения      = ВставитьЗнакВопроса(Объект.ХешСуммаРасширения);
		КонецЕсли;
	Иначе
		Объект.ПометкаУдаления = Ложь;
		
		ПолноеИмя = ОбъектМетаданных.ПолноеИмя();
		ПозицияТочки = СтрНайти(ПолноеИмя, ".");
		ИмяБазовогоТипа = Лев(ПолноеИмя, ПозицияТочки -1);
		
		СвойстваКоллекций = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений);
		Отбор = Новый Структура("ИмяВЕдЧисле", ИмяБазовогоТипа);
		Строки = СвойстваКоллекций.НайтиСтроки(Отбор);
		
		СвойстваОбъектовМетаданных = СвойстваОбъектовМетаданных(ОбъектыРасширений,
			СвойстваКоллекций.Скопировать(Строки));
		
		СвойстваОбъекта = СвойстваОбъектовМетаданных.Найти(ПолноеИмя, "ПолноеИмя");
		
		ЗаполнитьЗначенияСвойств(Объект, СвойстваОбъекта);
		
		Если ТипЗнч(Объект) <> Тип("ДанныеФормыСтруктура") Тогда
			КлючОбъектаМетаданных = Объект.КлючОбъектаМетаданных.Получить();
			Если КлючОбъектаМетаданных = Неопределено
			 ИЛИ СвойстваОбъекта.БезКлючаОбъектаМетаданных
			     <> (КлючОбъектаМетаданных = Тип("Неопределено")) Тогда
				
				Объект.КлючОбъектаМетаданных = Новый ХранилищеЗначения(КлючОбъектаМетаданных(СвойстваОбъекта.ПолноеИмя));
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования.
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//   * ПорядокБиблиотеки - Число
//   * ВерсияЧасть1 - Число
//   * ВерсияЧасть2 - Число
//   * ВерсияЧасть3 - Число
//   * ВерсияЧасть4 - Число
//   * ПорядокДобавления - Число
//   * СтароеПолноеИмя - Строка
//   * НовоеПолноеИмя - Строка
//
Функция ТаблицаПереименованияДляТекущейВерсии() Экспорт
	
	ТаблицаПереименования = Новый ТаблицаЗначений;
	ТаблицаПереименования.Колонки.Добавить("ПорядокБиблиотеки", Новый ОписаниеТипов("Число"));
	ТаблицаПереименования.Колонки.Добавить("ВерсияЧасть1",      Новый ОписаниеТипов("Число"));
	ТаблицаПереименования.Колонки.Добавить("ВерсияЧасть2",      Новый ОписаниеТипов("Число"));
	ТаблицаПереименования.Колонки.Добавить("ВерсияЧасть3",      Новый ОписаниеТипов("Число"));
	ТаблицаПереименования.Колонки.Добавить("ВерсияЧасть4",      Новый ОписаниеТипов("Число"));
	ТаблицаПереименования.Колонки.Добавить("ПорядокДобавления", Новый ОписаниеТипов("Число"));
	ТаблицаПереименования.Колонки.Добавить("СтароеПолноеИмя",   Новый ОписаниеТипов("Строка"));
	ТаблицаПереименования.Колонки.Добавить("НовоеПолноеИмя",    Новый ОписаниеТипов("Строка"));
	
	КоллекцииБезКлюча = Новый Соответствие;
	
	Отбор = Новый Структура("БезКлючаОбъектаМетаданных", Истина);
	
	КоллекцииБезКлючаОбъектаМетаданных =
		СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных().НайтиСтроки(Отбор);
	
	Для каждого Строка Из КоллекцииБезКлючаОбъектаМетаданных Цикл
		КоллекцииБезКлюча.Вставить(ВРег(Строка.ИмяВЕдЧисле), Строка.ИмяВЕдЧисле);
	КонецЦикла;
	КоллекцииБезКлюча.Вставить(ВРег("Роль"), "Роль");
	
	Итог = Новый Структура;
	Итог.Вставить("Таблица", ТаблицаПереименования);
	Итог.Вставить("КоллекцииБезКлюча", КоллекцииБезКлюча);
	Итог.Вставить("ВерсииБиблиотек",  Новый Соответствие);
	Итог.Вставить("ПорядокБиблиотек", Новый Соответствие);
	
	ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных(Итог);
	ИнтеграцияПодсистемБСП.ПриДобавленииПереименованийОбъектовМетаданных(Итог);
	
	ТаблицаПереименования.Сортировать(
		"ПорядокБиблиотеки ВОЗР,
		|ВерсияЧасть1 ВОЗР,
		|ВерсияЧасть2 ВОЗР,
		|ВерсияЧасть3 ВОЗР,
		|ВерсияЧасть4 ВОЗР,
		|ПорядокДобавления ВОЗР");
	
	Возврат ТаблицаПереименования;
	
КонецФункции

// Параметры:
//  ОбъектыРасширений - Булево
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//   * Имя              - Строка
//   * ИмяВЕдЧисле      - Строка
//   * Синоним          - Строка
//   * СинонимВЕдЧисле  - Строка
//   * ПорядокКоллекции - Строка
//   * БезДанных        - Булево
//   * БезКлючаОбъектаМетаданных - Булево
//   * Идентификатор             - УникальныйИдентификатор
//   * ОбъектыРасширений         - Булево
//
Функция СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений = Ложь) Экспорт
	
	Результат = Новый ТаблицаЗначений;
	Результат.Колонки.Добавить("Имя",                       Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(50)));
	Результат.Колонки.Добавить("ИмяВЕдЧисле",               Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(50)));
	Результат.Колонки.Добавить("Синоним",                   Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(255)));
	Результат.Колонки.Добавить("СинонимВЕдЧисле",           Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(255)));
	Результат.Колонки.Добавить("ПорядокКоллекции",          Новый ОписаниеТипов("Число"));
	Результат.Колонки.Добавить("БезДанных",                 Новый ОписаниеТипов("Булево"));
	Результат.Колонки.Добавить("БезКлючаОбъектаМетаданных", Новый ОписаниеТипов("Булево"));
	Результат.Колонки.Добавить("Идентификатор",             Новый ОписаниеТипов("УникальныйИдентификатор"));
	Результат.Колонки.Добавить("ОбъектыРасширений",         Новый ОписаниеТипов("Булево"));
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("627a6fb8-872a-11e3-bb87-005056c00008");
	Строка.Имя             = "Константы";
	Строка.Синоним         = НСтр("ru = 'Константы'");
	Строка.ИмяВЕдЧисле     = "Константа";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Константа'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("cdf5ac50-08e8-46af-9a80-4e63fd4a88ff");
	Строка.Имя             = "Подсистемы";
	Строка.Синоним         = НСтр("ru = 'Подсистемы'");
	Строка.ИмяВЕдЧисле     = "Подсистема";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Подсистема'");
	Строка.БезДанных       = Истина;
	Строка.БезКлючаОбъектаМетаданных = Истина;
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("115c4f55-9c20-4e86-a6d0-d0167ec053a1");
	Строка.Имя             = "Роли";
	Строка.Синоним         = НСтр("ru = 'Роли'");
	Строка.ИмяВЕдЧисле     = "Роль";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Роль'");
	Строка.БезДанных       = Истина;
	Строка.БезКлючаОбъектаМетаданных = Ложь;
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("269651e0-4b06-4f9d-aaab-a8d2b6bc6077");
	Строка.Имя             = "ПланыОбмена";
	Строка.Синоним         = НСтр("ru = 'Планы обмена'");
	Строка.ИмяВЕдЧисле     = "ПланОбмена";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'План обмена'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("ede89702-30f5-4a2a-8e81-c3a823b7e161");
	Строка.Имя             = "Справочники";
	Строка.Синоним         = НСтр("ru = 'Справочники'");
	Строка.ИмяВЕдЧисле     = "Справочник";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Справочник'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("96c6ab56-0375-40d5-99a2-b83efa3dac8b");
	Строка.Имя             = "Документы";
	Строка.Синоним         = НСтр("ru = 'Документы'");
	Строка.ИмяВЕдЧисле     = "Документ";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Документ'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("07938234-e29b-4cff-961a-9af07a4c6185");
	Строка.Имя             = "ЖурналыДокументов";
	Строка.Синоним         = НСтр("ru = 'Журналы документов'");
	Строка.ИмяВЕдЧисле     = "ЖурналДокументов";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Журнал документов'");
	Строка.БезДанных       = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("706cf832-0ae5-45b5-8a4a-1f251d054f3b");
	Строка.Имя             = "Отчеты";
	Строка.Синоним         = НСтр("ru = 'Отчеты'");
	Строка.ИмяВЕдЧисле     = "Отчет";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Отчет'");
	Строка.БезДанных       = Истина;
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("ae480426-487e-40b2-98ba-d207777449f3");
	Строка.Имя             = "Обработки";
	Строка.Синоним         = НСтр("ru = 'Обработки'");
	Строка.ИмяВЕдЧисле     = "Обработка";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Обработка'");
	Строка.БезДанных       = Истина;
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("8b5649b9-cdd1-4698-9aac-12ba146835c4");
	Строка.Имя             = "ПланыВидовХарактеристик";
	Строка.Синоним         = НСтр("ru = 'Планы видов характеристик'");
	Строка.ИмяВЕдЧисле     = "ПланВидовХарактеристик";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'План видов характеристик'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("4295af27-543f-4373-bcfc-c0ace9b7620c");
	Строка.Имя             = "ПланыСчетов";
	Строка.Синоним         = НСтр("ru = 'Планы счетов'");
	Строка.ИмяВЕдЧисле     = "ПланСчетов";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'План счетов'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("fca3e7e1-1bf1-49c8-9921-aafb4e787c75");
	Строка.Имя             = "ПланыВидовРасчета";
	Строка.Синоним         = НСтр("ru = 'Планы видов расчета'");
	Строка.ИмяВЕдЧисле     = "ПланВидовРасчета";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'План видов расчета'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("d7ecc1e9-c068-44dd-83c2-1323ec52dbbb");
	Строка.Имя             = "РегистрыСведений";
	Строка.Синоним         = НСтр("ru = 'Регистры сведений'");
	Строка.ИмяВЕдЧисле     = "РегистрСведений";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Регистр сведений'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("74083488-b01e-4441-84a6-c386ce88cdb5");
	Строка.Имя             = "РегистрыНакопления";
	Строка.Синоним         = НСтр("ru = 'Регистры накопления'");
	Строка.ИмяВЕдЧисле     = "РегистрНакопления";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Регистр накопления'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("9a0d75ff-0eda-454e-b2b7-d2412ffdff18");
	Строка.Имя             = "РегистрыБухгалтерии";
	Строка.Синоним         = НСтр("ru = 'Регистры бухгалтерии'");
	Строка.ИмяВЕдЧисле     = "РегистрБухгалтерии";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Регистр бухгалтерии'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("f330686a-0acf-4e26-9cda-108f1404687d");
	Строка.Имя             = "РегистрыРасчета";
	Строка.Синоним         = НСтр("ru = 'Регистры расчета'");
	Строка.ИмяВЕдЧисле     = "РегистрРасчета";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Регистр расчета'");
	Строка.ОбъектыРасширений = Истина;
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("a8cdd0e0-c27f-4bf0-9718-10ec054dc468");
	Строка.Имя             = "БизнесПроцессы";
	Строка.Синоним         = НСтр("ru = 'Бизнес-процессы'");
	Строка.ИмяВЕдЧисле     = "БизнесПроцесс";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Бизнес-процесс'");
	
	Строка = Результат.Добавить();
	Строка.Идентификатор   = Новый УникальныйИдентификатор("8d9153ad-7cea-4e25-9542-a557ee59fd16");
	Строка.Имя             = "Задачи";
	Строка.Синоним         = НСтр("ru = 'Задачи'");
	Строка.ИмяВЕдЧисле     = "Задача";
	Строка.СинонимВЕдЧисле = НСтр("ru = 'Задача'");
	
	Для каждого Строка Из Результат Цикл
		Строка.ПорядокКоллекции = Результат.Индекс(Строка);
	КонецЦикла;
	
	Если ОбъектыРасширений Тогда
		Результат = Результат.Скопировать(Новый Структура("ОбъектыРасширений", Истина));
	КонецЕсли;
	
	Результат.Индексы.Добавить("Идентификатор");
	Результат.Индексы.Добавить("Имя");
	
	Возврат Результат;
	
КонецФункции

// Предотвращает недопустимое изменение идентификаторов объектов метаданных.
// Выполняет обработку дублей подчиненного узла распределенной информационной базы.
//
// Параметры:
//   Объект - СправочникОбъект.ИдентификаторыОбъектовМетаданных
//          - СправочникОбъект.ИдентификаторыОбъектовРасширений
//
Процедура ПередЗаписьюОбъекта(Объект) Экспорт
	
	ОбъектыРасширений = ЭтоОбъектРасширений(Объект);
	СтандартныеПодсистемыПовтИсп.ИдентификаторыОбъектовМетаданныхПроверкаИспользования(, ОбъектыРасширений);
	
	// Отключение механизма регистрации объектов.
	Объект.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов");
	
	// Регистрация объекта на всех узлах РИБ.
	Для Каждого ПланОбмена Из СтандартныеПодсистемыПовтИсп.ПланыОбменаРИБ() Цикл
		СтандартныеПодсистемыСервер.ЗарегистрироватьОбъектНаВсехУзлах(Объект, ПланОбмена, Ложь);
	КонецЦикла;
	
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);
	
	ВыполненоОбновление = Новый Структура(ПараметрыСеанса.ОбновлениеСправочниковИдентификаторов);
	Если ОбъектыРасширений Тогда
		ВыполненоОбновление.ИдентификаторыОбъектовРасширений = Ложь;
	Иначе
		ВыполненоОбновление.ИдентификаторыОбъектовМетаданных = Ложь;
	КонецЕсли;
	ПараметрыСеанса.ОбновлениеСправочниковИдентификаторов = Новый ФиксированнаяСтруктура(ВыполненоОбновление);
	
	УстановитьПривилегированныйРежим(Ложь);
	УстановитьОтключениеБезопасногоРежима(Ложь);
	
	Если Объект.ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;
	
	ПроверитьОбъектПередЗаписью(Объект);
	
КонецПроцедуры

// Предотвращает удаление идентификаторов объектов метаданных не помеченных на удаление.
//
// Параметры:
//   Объект - СправочникОбъект.ИдентификаторыОбъектовМетаданных
//          - СправочникОбъект.ИдентификаторыОбъектовРасширений
//
Процедура ПередУдалениемОбъекта(Объект) Экспорт
	
	ОбъектыРасширений = ЭтоОбъектРасширений(Объект);
	СтандартныеПодсистемыПовтИсп.ИдентификаторыОбъектовМетаданныхПроверкаИспользования(, ОбъектыРасширений);
	
	// Отключение механизма регистрации объектов.
	// Ссылки идентификаторов удаляются независимо во всех узлах
	// через механизм пометки удаления и удаления помеченных объектов.
	Объект.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов");
	
	Если Объект.ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;
	
	Если Не Объект.ПометкаУдаления Тогда
		ВызватьИсключениеПоОшибке(ОбъектыРасширений,
			НСтр("ru = 'Удаление идентификаторов объектов, у которых значение
			           |реквизита ""Пометка удаления"" установлено Ложь недопустимо.'"));
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования.
// 
// Параметры:
//  Форма - ФормаКлиентскогоПриложения:
//   * Список - ДинамическийСписок
//
Процедура ФормаСпискаПриСозданииНаСервере(Форма) Экспорт
	
	Параметры = Форма.Параметры;
	Элементы  = Форма.Элементы;
	
	УпорядочитьИОформитьСписок(Форма);
	
	Если Параметры.РежимВыбора Тогда
		СтандартныеПодсистемыСервер.УстановитьКлючНазначенияФормы(Форма, "ВыборПодбор");
		Форма.РежимОткрытияОкна = РежимОткрытияОкнаФормы.БлокироватьОкноВладельца;
	Иначе
		Элементы.Список.РежимВыбора = Ложь;
	КонецЕсли;
	
	Параметры.Свойство("ВыбиратьГруппыОбъектовМетаданных", Форма.ВыбиратьГруппыОбъектовМетаданных);
	
КонецПроцедуры

// Только для внутреннего использования.
// 
// Параметры:
//  Форма - ФормаКлиентскогоПриложения:
//   * Объект - ДанныеФормыСтруктура:
//    ** Ссылка - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//              - СправочникСсылка.ИдентификаторыОбъектовРасширений
//    
Процедура ФормаЭлементаПриСозданииНаСервере(Форма) Экспорт
	
	ОбъектыРасширений = ЭтоОбъектРасширений(Форма.Объект.Ссылка);
	
	Элементы  = Форма.Элементы;
	
	Форма.ТолькоПросмотр = Истина;
	Форма.ПустаяСсылкаПредставление = Строка(ТипЗнч(Форма.Объект.ЗначениеПустойСсылки));
	
	Если НЕ Пользователи.ЭтоПолноправныйПользователь(, Не ОбъектыРасширений)
	 ИЛИ ЗапрещеноИзменятьПолноеИмя(Форма.Объект)
	 ИЛИ Не ОбъектыРасширений И ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ()
	 ИЛИ ОбъектыРасширений И Справочники.ИдентификаторыОбъектовРасширений.ОбъектРасширенияОтключен(Форма.Объект.Ссылка) Тогда
		
		Элементы.ФормаВключитьВозможностьРедактирования.Видимость = Ложь;
	КонецЕсли;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Вспомогательные процедуры и функции.

// Для процедуры ЗагрузитьДанныеВПодчиненныйУзел.
// 
// Параметры:
//  Выгрузка - см. ВыгрузкаВсехИдентификаторов
//
Процедура ОпределитьДублиПриЗагрузкеВПодчиненныйУзел(Выгрузка, Отбор, ЗагружаемыйОбъект, СсылкаЗагружаемого, ТаблицаЗагружаемых)
	
	Строки = Выгрузка.НайтиСтроки(Отбор);
	Для Каждого Строка Из Строки Цикл
		
		Если Строка.Ссылка <> СсылкаЗагружаемого
		   И ТаблицаЗагружаемых.Найти(Строка.Ссылка, "Ссылка") = Неопределено Тогда
			
			ОбновитьСвойстваПомеченногоНаУдаление(Строка,,, Истина);
			Строка.НоваяСсылка = СсылкаЗагружаемого;
			Строка.ДубльОбновлен = Истина;
			ЗагружаемыйОбъект.ДополнительныеСвойства.Вставить("ЭтоЗаменаДубля");
			// Замена новых ссылок на дубль на новую ссылку заданную для дубля (если есть).
			СтарыеДубли = Выгрузка.НайтиСтроки(Новый Структура("НоваяСсылка", Строка.Ссылка));
			Для Каждого СтарыйДубль Из СтарыеДубли Цикл
				ОбновитьСвойстваПомеченногоНаУдаление(СтарыйДубль,,, Истина);
				СтарыйДубль.НоваяСсылка = СсылкаЗагружаемого;
				СтарыйДубль.ДубльОбновлен = Истина;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

Процедура ОбновитьДанные(ЕстьИзменения, ЕстьУдаленные, ТолькоПроверка,
			ЕстьКритичныеИзменения, СписокКритичныхИзменений, ОбъектыРасширений)
	
	Если ОбъектыРасширений Тогда
		СвойстваРасширений = Новый Структура;
		РасширенияБазыДанных = Новый Массив;
		ИдентификаторыКлючейРасширений = ИдентификаторыКлючейРасширений(РасширенияБазыДанных);
		СвойстваРасширений.Вставить("ИменаПодключенныхРасширений",
			ИменаРасширений(ИсточникРасширенийКонфигурации.СеансАктивные, ИдентификаторыКлючейРасширений));
		СвойстваРасширений.Вставить("ИменаНеподключенныхРасширений",
			ИменаРасширений(ИсточникРасширенийКонфигурации.СеансОтключенные, ИдентификаторыКлючейРасширений));
		ДополнитьИменаНеподключенныхРасширенийВСеансеБезРазделителей(СвойстваРасширений, РасширенияБазыДанных);
	КонецЕсли;
	
	СвойстваОбъектовМетаданных = СвойстваОбъектовМетаданных(ОбъектыРасширений,, ИдентификаторыКлючейРасширений);
	
	// Найден - состояние, когда для объекта метаданных найден идентификатор.
	СвойстваОбъектовМетаданных.Колонки.Добавить("Найден", Новый ОписаниеТипов("Булево"));
	
	// Порядок обновления:
	// 1. Переименование объектов метаданных (с учетом нижестоящих подсистем).
	// 2. Обновление предопределенных идентификаторов (коллекций объектов метаданных).
	// 3. Обновление идентификаторов объектов метаданных, которые    имеют ключ  объекта метаданных.
	// 4. Обновление идентификаторов объектов метаданных, которые не имеют ключа объекта метаданных.
	// 5. В процессе 3 и 4 пометка удаления дублей идентификаторов (по полным именам).
	// 6. Добавление новых идентификаторов объектов метаданных.
	// 7. Обновление родителей идентификаторов объектов метаданных и запись обновленных.
	
	ВерсияРасширений = ПараметрыСеанса.ВерсияРасширений;
	
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить(ИмяСправочника(ОбъектыРасширений));
	Если ОбъектыРасширений Тогда
		ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ИдентификаторыОбъектовВерсийРасширений");
		ЭлементБлокировки.УстановитьЗначение("ВерсияРасширений", ВерсияРасширений);
	КонецЕсли;
	
	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		
		Выгрузка = ВыгрузкаВсехИдентификаторов(ОбъектыРасширений);
		Выгрузка.Колонки.Добавить("Обновлен", Новый ОписаниеТипов("Булево"));
		Выгрузка.Колонки.Добавить("ОбъектМетаданных");
		Выгрузка.Колонки.Удалить("НоваяСсылка");
		
		СписокПереименованийОбъектовМетаданных = "";
		Если НЕ ОбъектыРасширений
		   И НЕ ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
			// Переименование полных имен перед обработкой (для РИБ только в главном узле).
			// Для расширений не поддерживается.
			ПереименоватьПолныеИмена(Выгрузка, СписокПереименованийОбъектовМетаданных, ЕстьКритичныеИзменения);
		КонецЕсли;
		
		ОбработатьИдентификаторыОбъектовМетаданных(Выгрузка, СвойстваОбъектовМетаданных, ОбъектыРасширений,
			СвойстваРасширений, ЕстьУдаленные, ЕстьКритичныеИзменения, СписокПереименованийОбъектовМетаданных);
		
		СписокНовыхОбъектовМетаданных = "";
		ДобавитьИдентификаторыНовыхОбъектовМетаданных(Выгрузка, СвойстваОбъектовМетаданных, ОбъектыРасширений,
			ЕстьКритичныеИзменения, СписокНовыхОбъектовМетаданных);
		
		СписокКритичныхИзменений = "";
		Если ЗначениеЗаполнено(СписокПереименованийОбъектовМетаданных) Тогда
			СписокКритичныхИзменений = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Переименование идентификаторов объектов метаданных %1 -> %2:'"),
				"СтароеПолноеИмя",
				"НовоеПолноеИмя");
			СписокКритичныхИзменений = СписокКритичныхИзменений + Символы.ПС
				+ СписокПереименованийОбъектовМетаданных + Символы.ПС + Символы.ПС;
		КонецЕсли;
		Если ЗначениеЗаполнено(СписокНовыхОбъектовМетаданных) Тогда
			СписокКритичныхИзменений = СписокКритичныхИзменений
				+ НСтр("ru = 'Добавление новых идентификаторов объектов метаданных:'")
				+ Символы.ПС + СписокНовыхОбъектовМетаданных + Символы.ПС;
		КонецЕсли;
		
		Если Не ТолькоПроверка
		   И Не ОбъектыРасширений
		   И ЗначениеЗаполнено(СписокКритичныхИзменений)
		   И ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
			
			ИмяСобытия = НСтр("ru = 'Идентификаторы объектов метаданных.Требуется загрузить критичные изменения'",
				ОбщегоНазначения.КодОсновногоЯзыка());
			
			ЖурналРегистрации.ДобавитьСообщениеДляЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Ошибка, , , СписокКритичныхИзменений);
			
			ВызватьИсключениеПоОшибке(ОбъектыРасширений,
				НСтр("ru = 'Критичные изменения могут быть выполнены только
				           |в главном узле распределенной информационной базы.
				           |Состав требуемых изменений см. в журнале регистрации.'"));
		КонецЕсли;
		
		ЕстьТекущиеИзменения = Ложь;
		ОбновитьИдентификаторыОбъектовМетаданных(Выгрузка, СвойстваОбъектовМетаданных, ОбъектыРасширений,
			СвойстваРасширений, ВерсияРасширений, ЕстьТекущиеИзменения, ТолькоПроверка);
		
		Если ЕстьТекущиеИзменения Тогда
			ЕстьИзменения = Истина;
		КонецЕсли;
		
		Если Не ТолькоПроверка Тогда
			Если Не ОбъектыРасширений И ЕстьТекущиеИзменения Тогда
				СтандартныеПодсистемыСервер.ПроверитьДинамическоеОбновлениеВерсииПрограммы();
			КонецЕсли;
			Если ЗначениеЗаполнено(СписокКритичныхИзменений) Тогда
				ЖурналРегистрации.ДобавитьСообщениеДляЖурналаРегистрации(?(ОбъектыРасширений,
						НСтр("ru = 'Идентификаторы объектов расширений.Выполнены критичные изменения'",
							ОбщегоНазначения.КодОсновногоЯзыка()),
						НСтр("ru = 'Идентификаторы объектов метаданных.Выполнены критичные изменения'",
							ОбщегоНазначения.КодОсновногоЯзыка())),
					УровеньЖурналаРегистрации.Информация,,,
					СписокКритичныхИзменений);
			КонецЕсли;
			
			Если Не ОбъектыРасширений
			   И Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
				
				ПодготовитьСписокНовыхПодсистемВГлавномУзле(Выгрузка);
			КонецЕсли;
		КонецЕсли;
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

// Возвращаемое значение:
//  ТаблицаЗначений:
//   * Ссылка - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//            - СправочникСсылка.ИдентификаторыОбъектовРасширений
//   * ИмяПредопределенныхДанных - Строка
//   * Родитель - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//              - СправочникСсылка.ИдентификаторыОбъектовРасширений
//   * ПометкаУдаления - Булево
//   * Наименование - Строка
//   * ПорядокКоллекции - Число
//   * Имя - Строка
//   * Синоним - Строка
//   * ПолноеИмя - Строка
//   * ПолныйСиноним - Строка
//   * БезДанных - Булево
//   * ЗначениеПустойСсылки - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//                          - СправочникСсылка.ИдентификаторыОбъектовРасширений
//   * ХранилищеКлюча - ХранилищеЗначения
//   * НоваяСсылка - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//                 - СправочникСсылка.ИдентификаторыОбъектовРасширений
//   * ИмяРасширения - Строка
//   * ИдентификаторРасширения - Строка
//   * ХешСуммаРасширения - Строка
//   * КлючОбъектаМетаданных - Тип
//                           - Строка
//                           - Неопределено
//   * БезКлючаОбъектаМетаданных - Булево
//   * ЭтоКоллекция - Булево
//   * ЭтоНовый - Булево
//
Функция ВыгрузкаВсехИдентификаторов(ОбъектыРасширений = Ложь)
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Идентификаторы.Ссылка КАК Ссылка,
	|	Идентификаторы.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных,
	|	Идентификаторы.Родитель КАК Родитель,
	|	Идентификаторы.ПометкаУдаления КАК ПометкаУдаления,
	|	Идентификаторы.Наименование КАК Наименование,
	|	Идентификаторы.ПорядокКоллекции,
	|	Идентификаторы.Имя,
	|	Идентификаторы.Синоним,
	|	Идентификаторы.ПолноеИмя,
	|	Идентификаторы.ПолныйСиноним,
	|	Идентификаторы.БезДанных,
	|	Идентификаторы.ЗначениеПустойСсылки,
	|	Идентификаторы.КлючОбъектаМетаданных КАК ХранилищеКлюча,
	|	Идентификаторы.НоваяСсылка,
	|	&ИмяРасширения КАК ИмяРасширения,
	|	&ИдентификаторРасширения КАК ИдентификаторРасширения,
	|	&ХешСуммаРасширения КАК ХешСуммаРасширения
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовМетаданных КАК Идентификаторы";
	УточнитьИмяСправочникаВТекстеЗапроса(Запрос.Текст, ОбъектыРасширений);
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИмяРасширения",
		?(ОбъектыРасширений, "Идентификаторы.ИмяРасширения", """"""));
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИдентификаторРасширения",
		?(ОбъектыРасширений, "Идентификаторы.ИдентификаторРасширения", """"""));
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ХешСуммаРасширения",
		?(ОбъектыРасширений, "Идентификаторы.ХешСуммаРасширения", """"""));
	
	Выгрузка = Запрос.Выполнить().Выгрузить();
	Выгрузка.Колонки.Добавить("КлючОбъектаМетаданных");
	Выгрузка.Колонки.Добавить("БезКлючаОбъектаМетаданных", Новый ОписаниеТипов("Булево"));
	Выгрузка.Колонки.Добавить("ЭтоКоллекция",              Новый ОписаниеТипов("Булево"));
	Выгрузка.Колонки.Добавить("ЭтоНовый",                  Новый ОписаниеТипов("Булево"));
	
	// Упорядочение идентификаторов перед обработкой.
	Для Каждого Строка Из Выгрузка Цикл
		Если Не ЗначениеЗаполнено(Строка.Ссылка) Тогда
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Данные справочника %1 повреждены.
				           |В конфигураторе в меню ""Администрирование""
				           |выполните ""Тестирование и исправление..."".'"),
				?(ОбъектыРасширений, "ИдентификаторыОбъектовРасширений", "ИдентификаторыОбъектовМетаданных"));
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
		Если ТипЗнч(Строка.ХранилищеКлюча) = Тип("ХранилищеЗначения") Тогда
			Строка.КлючОбъектаМетаданных = Строка.ХранилищеКлюча.Получить();
		Иначе
			Строка.КлючОбъектаМетаданных = Неопределено;
		КонецЕсли;
		Строка.БезКлючаОбъектаМетаданных = Строка.КлючОбъектаМетаданных = Неопределено
		                               Или Строка.КлючОбъектаМетаданных = Тип("Неопределено");
	КонецЦикла;
	
	Выгрузка.Индексы.Добавить("Ссылка");
	Выгрузка.Индексы.Добавить("ПолноеИмя");
	
	СвойстваКоллекций = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений);
	
	Для Каждого СвойстваКоллекции Из СвойстваКоллекций Цикл
		ИдентификаторКоллекции = ИдентификаторКоллекции(СвойстваКоллекции.Идентификатор, ОбъектыРасширений);
		Строка = Выгрузка.Найти(ИдентификаторКоллекции, "Ссылка");
		Если Строка = Неопределено Тогда
			Строка = Выгрузка.Добавить();
			Строка.Ссылка   = ИдентификаторКоллекции;
			Строка.ЭтоНовый = Истина;
		КонецЕсли;
		Строка.ЭтоКоллекция = Истина;
	КонецЦикла;
	
	Выгрузка.Сортировать("ЭтоКоллекция УБЫВ,
	                     |ПометкаУдаления ВОЗР,
	                     |БезКлючаОбъектаМетаданных ВОЗР");
	
	Возврат Выгрузка;
	
КонецФункции

Процедура ПереименоватьПолныеИмена(Выгрузка, СписокПереименованийОбъектовМетаданных = "", ЕстьКритичныеИзменения = Ложь)
	
	ТаблицаПереименования = СтандартныеПодсистемыПовтИсп.ТаблицаПереименованияДляТекущейВерсии();
	Переименованные = Новый Соответствие;
	
	Для Каждого ОписаниеПереименования Из ТаблицаПереименования Цикл
		ДлинаСтарогоПолногоИмени = СтрДлина(ОписаниеПереименования.СтароеПолноеИмя);
		ЭтоПодсистема = ВРег(Лев(ОписаниеПереименования.СтароеПолноеИмя,
			СтрДлина("Подсистема."))) = ВРег("Подсистема.");
		
		Для Каждого Строка Из Выгрузка Цикл
			Если Строка.ЭтоКоллекция Тогда
				Продолжить;
			КонецЕсли;
			
			НовоеПолноеИмя = "";
			
			Если ЭтоПодсистема Тогда
				Если ВРег(Лев(Строка.ПолноеИмя, ДлинаСтарогоПолногоИмени))
				     = ВРег(ОписаниеПереименования.СтароеПолноеИмя) Тогда
					
					НовоеПолноеИмя = ОписаниеПереименования.НовоеПолноеИмя
						+ Сред(Строка.ПолноеИмя, ДлинаСтарогоПолногоИмени + 1);
				КонецЕсли;
			Иначе
				Если ВРег(Строка.ПолноеИмя) = ВРег(ОписаниеПереименования.СтароеПолноеИмя) Тогда
					НовоеПолноеИмя = ОписаниеПереименования.НовоеПолноеИмя;
				КонецЕсли;
			КонецЕсли;
			
			Если Не ЗначениеЗаполнено(НовоеПолноеИмя) Тогда
				Продолжить;
			КонецЕсли;
			
			Переименование = Переименованные.Получить(Строка);
			Если Переименование = Неопределено Тогда
				Переименование = Новый Структура;
				Переименование.Вставить("СтароеПолноеИмя", Строка.ПолноеИмя);
				Переименование.Вставить("НовоеПолноеИмя",  НовоеПолноеИмя);
				Переименованные.Вставить(Строка, Переименование);
			Иначе
				Переименование.НовоеПолноеИмя = НовоеПолноеИмя;
			КонецЕсли;
			Строка.ПолноеИмя = НовоеПолноеИмя;
			Строка.Обновлен = Истина;
		КонецЦикла;
	КонецЦикла;
	
	Для Каждого Строка Из Выгрузка Цикл
		Переименование = Переименованные.Получить(Строка);
		Если Переименование = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		ЕстьКритичныеИзменения = Истина;
		СписокПереименованийОбъектовМетаданных = СписокПереименованийОбъектовМетаданных
			+ ?(ЗначениеЗаполнено(СписокПереименованийОбъектовМетаданных), "," + Символы.ПС, "")
			+ Переименование.СтароеПолноеИмя + " -> " + Переименование.НовоеПолноеИмя;
	КонецЦикла;
	
КонецПроцедуры

Процедура ОбработатьИдентификаторыОбъектовМетаданных(Выгрузка, СвойстваОбъектовМетаданных, ОбъектыРасширений,
			СвойстваРасширений, ЕстьУдаленные, ЕстьКритичныеИзменения, СписокПереименованийОбъектовМетаданных)
	
	// Обработка идентификаторов объектов метаданных.
	Для Каждого Свойства Из Выгрузка Цикл
		
		// Проверка и обновление свойств идентификаторов коллекций объектов метаданных.
		Если Свойства.ЭтоКоллекция Тогда
			ПроверитьОбновитьСвойстваКоллекции(Свойства, ОбъектыРасширений);
			Продолжить;
		КонецЕсли;
		
		Если ОбъектыРасширений
		   И (    СвойстваРасширений.ИменаНеподключенныхРасширений[НРег(Свойства.ИмяРасширения)] <> Неопределено
		      Или СвойстваРасширений.ИменаНеподключенныхРасширений[НРег(Свойства.ИдентификаторРасширения)] <> Неопределено)Тогда
			// Для случаев, когда расширение было временно отключено, а затем подключено обратно,
			// предотвращаем удаление помеченных элементов и связанных с ними данных.
			Продолжить;
		КонецЕсли;
		
		Если ОбъектыРасширений
		   И СвойстваРасширений.ИменаПодключенныхРасширений[НРег(Свойства.ИмяРасширения)] = Неопределено
		   И СвойстваРасширений.ИменаПодключенныхРасширений[НРег(Свойства.ИдентификаторРасширения)] = Неопределено Тогда
			
			СвойстваОбновлены = Ложь;
			ОбновитьСвойстваПомеченногоНаУдаление(Свойства, СвойстваОбновлены, ЕстьУдаленные);
			Если СвойстваОбновлены Тогда
				Свойства.Обновлен = Истина;
			КонецЕсли;
		КонецЕсли;
		
		КлючОбъектаМетаданных = Свойства.КлючОбъектаМетаданных;
		ОбъектМетаданных = ОбъектМетаданныхПоКлючу(КлючОбъектаМетаданных,
			Свойства.ИмяРасширения, Свойства.ИдентификаторРасширения, Свойства.ХешСуммаРасширения);
		
		Если ОбъектМетаданных = Неопределено Тогда
			Если КлючОбъектаМетаданных = Тип("Неопределено") Тогда
				// Если объект метаданных без ключа, то его можно найти только по полному имени.
				ОбъектМетаданных = МетаданныеНайтиПоПолномуИмени(Свойства.ПолноеИмя);
				Если ОбъектМетаданных = Неопределено И ОбъектыРасширений Тогда
					ОбъектМетаданных = МетаданныеРасширенияНайтиПоПолномуИмени(Свойства);
				КонецЕсли;
			КонецЕсли;
		Иначе
			// Если объект метаданных удалялся с целью реструктуризации, тогда
			// старый идентификатор нужно использовать для нового объекта метаданных,
			// а для старых объектов метаданных создать новые идентификаторы.
			Если ВРег(Лев(ОбъектМетаданных.Имя, СтрДлина("Удалить"))) =  ВРег("Удалить")
			   И ВРег(Лев(Свойства.Имя,         СтрДлина("Удалить"))) <> ВРег("Удалить") Тогда
				
				НовыйОбъектМетаданных = МетаданныеНайтиПоПолномуИмени(Свойства.ПолноеИмя);
				Если НовыйОбъектМетаданных <> Неопределено Тогда
					ОбъектМетаданных = НовыйОбъектМетаданных;
					КлючОбъектаМетаданных = Неопределено; // Чтобы выполнить обновление идентификатора.
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		
		// Если объект метаданных найден по ключу или полному имени,
		// тогда нужно подготовить строку свойств объекта метаданных.
		Если ОбъектМетаданных <> Неопределено Тогда
			СвойстваОбъекта = СвойстваОбъектовМетаданных.Найти(ОбъектМетаданных.ПолноеИмя(), "ПолноеИмя");
			Если СвойстваОбъекта = Неопределено Тогда
				ОбъектМетаданных = Неопределено;
			Иначе
				Свойства.ОбъектМетаданных = ОбъектМетаданных;
			КонецЕсли;
		КонецЕсли;
		
		Если ОбъектМетаданных = Неопределено ИЛИ СвойстваОбъекта.Найден Тогда
			// Если объект метаданных не найден или найден повторно
			// тогда идентификатор требуется пометить на удаление.
			ЭтоДубль = ОбъектМетаданных <> Неопределено И СвойстваОбъекта.Найден;
			СвойстваОбновлены = Ложь;
			ОбновитьСвойстваПомеченногоНаУдаление(Свойства, СвойстваОбновлены, ЕстьУдаленные, ЭтоДубль);
			Если СвойстваОбновлены Тогда
				Свойства.Обновлен = Истина;
			КонецЕсли;
		Иначе
			// Обновление свойств существующих объектов метаданных, если изменились.
			СвойстваОбъекта.Найден = Истина;
			Если Свойства.Наименование              <> СвойстваОбъекта.Наименование
			 ИЛИ Свойства.ПорядокКоллекции          <> СвойстваОбъекта.ПорядокКоллекции
			 ИЛИ Свойства.Имя                       <> СвойстваОбъекта.Имя
			 ИЛИ Свойства.Синоним                   <> СвойстваОбъекта.Синоним
			 ИЛИ Свойства.ПолноеИмя                 <> СвойстваОбъекта.ПолноеИмя
			 ИЛИ Свойства.ПолныйСиноним             <> СвойстваОбъекта.ПолныйСиноним
			 ИЛИ Свойства.БезДанных                 <> СвойстваОбъекта.БезДанных
			 ИЛИ Свойства.ЗначениеПустойСсылки      <> СвойстваОбъекта.ЗначениеПустойСсылки
			 ИЛИ Свойства.ИмяРасширения             <> СвойстваОбъекта.ИмяРасширения
			 ИЛИ Свойства.ИдентификаторРасширения   <> СвойстваОбъекта.ИдентификаторРасширения
			 ИЛИ Свойства.ХешСуммаРасширения        <> СвойстваОбъекта.ХешСуммаРасширения
			 ИЛИ Свойства.ИмяПредопределенныхДанных <> СвойстваОбъекта.ИмяПредопределенныхДанных
			 ИЛИ Свойства.ПометкаУдаления
			 ИЛИ КлючОбъектаМетаданных = Неопределено
			 ИЛИ СвойстваОбъекта.БезКлючаОбъектаМетаданных
			     <> (КлючОбъектаМетаданных = Тип("Неопределено")) Тогда
				
				Если ВРег(Свойства.ПолноеИмя) <> ВРег(СвойстваОбъекта.ПолноеИмя) Тогда
					ЕстьКритичныеИзменения = Истина;
					СписокПереименованийОбъектовМетаданных = СписокПереименованийОбъектовМетаданных
						+ ?(ЗначениеЗаполнено(СписокПереименованийОбъектовМетаданных), "," + Символы.ПС, "")
						+ Свойства.ПолноеИмя + " -> " + СвойстваОбъекта.ПолноеИмя;
				КонецЕсли;
				
				// Установка новых свойств идентификатора объекта метаданных.
				ЗаполнитьЗначенияСвойств(Свойства, СвойстваОбъекта);
				
				Свойства.ИмяПредопределенныхДанных = СвойстваОбъекта.ИмяПредопределенныхДанных;
				
				Если КлючОбъектаМетаданных = Неопределено
				 ИЛИ СвойстваОбъекта.БезКлючаОбъектаМетаданных
				     <> (КлючОбъектаМетаданных = Тип("Неопределено")) Тогда
					
					Свойства.КлючОбъектаМетаданных = КлючОбъектаМетаданных(СвойстваОбъекта.ПолноеИмя);
				КонецЕсли;
				
				Свойства.ПометкаУдаления = Ложь;
				Свойства.Обновлен = Истина;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

Функция МетаданныеРасширенияНайтиПоПолномуИмени(Свойства)
	
	Если Свойства.ИмяРасширения = ""
	 Или Не СтрНачинаетсяС(Свойства.ПолноеИмя, "? ") Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	// Восстановление связи с идентификатором объекта метаданных расширения,
	// которое было временно удалено и восстанавливается.
	ИсходноеПолноеИмя = ПолноеИмяУдаленного(Свойства.ПолноеИмя);
	ОбъектМетаданных = МетаданныеНайтиПоПолномуИмени(ИсходноеПолноеИмя);
	
	Если ОбъектМетаданных = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	РасширениеОбъекта = ОбъектМетаданных.РасширениеКонфигурации();
	Если РасширениеОбъекта = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если НРег(РасширениеОбъекта.УникальныйИдентификатор) = НРег(Сред(Свойства.ИдентификаторРасширения, 3))
	 Или НРег(РасширениеОбъекта.Имя) = НРег(Сред(Свойства.ИмяРасширения, 3)) Тогда
		
		Возврат ОбъектМетаданных;
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

Функция ИдентификаторыКлючейРасширений(РасширенияБазыДанных = Неопределено)
	
	Расширения = РасширенияКонфигурации.Получить();
	ИдентификаторыКлючейРасширений = Новый Соответствие;
	Для Каждого Расширение Из Расширения Цикл
		КлючРасширения = НРег(Расширение.Имя) + " " + Base64Строка(Расширение.ХешСумма);
		ИдентификаторыКлючейРасширений.Вставить(КлючРасширения, НРег(Расширение.УникальныйИдентификатор));
		Если ТипЗнч(РасширенияБазыДанных) = Тип("Массив") Тогда
			РасширенияБазыДанных.Добавить(Расширение);
		КонецЕсли;
	КонецЦикла;
	
	Возврат ИдентификаторыКлючейРасширений;
	
КонецФункции

Процедура ДобавитьИдентификаторыНовыхОбъектовМетаданных(Выгрузка, СвойстваОбъектовМетаданных, ОбъектыРасширений,
			ЕстьКритичныеИзменения, СписокНовыхОбъектовМетаданных)
	
	СвойстваОбъектов = СвойстваОбъектовМетаданных.НайтиСтроки(Новый Структура("Найден", Ложь));
	
	Для Каждого СвойстваОбъекта Из СвойстваОбъектов Цикл
		Свойства = Выгрузка.Добавить();
		ЗаполнитьЗначенияСвойств(Свойства, СвойстваОбъекта);
		Свойства.ЭтоНовый = Истина;
		Свойства.Ссылка = НоваяСсылкаСправочника(ОбъектыРасширений);
		Свойства.ПометкаУдаления  = Ложь;
		Свойства.ОбъектМетаданных = СвойстваОбъекта.ОбъектМетаданных;
		Свойства.КлючОбъектаМетаданных = КлючОбъектаМетаданных(Свойства.ПолноеИмя);
		ЕстьКритичныеИзменения = Истина;
		СписокНовыхОбъектовМетаданных = СписокНовыхОбъектовМетаданных
			+ ?(ЗначениеЗаполнено(СписокНовыхОбъектовМетаданных), "," + Символы.ПС, "")
			+ СвойстваОбъекта.ПолноеИмя;
	КонецЦикла;
	
КонецПроцедуры

Процедура ОбновитьИдентификаторыОбъектовМетаданных(Выгрузка, СвойстваОбъектовМетаданных, ОбъектыРасширений,
			СвойстваРасширений, ВерсияРасширений, ЕстьИзменения, ТолькоПроверка)
		
	// АПК:1327-выкл - №783.1.4.1 Управляемая блокировка устанавливается в вызывающем коде.
	Если ОбъектыРасширений Тогда
		НаборЗаписей = РегистрыСведений.ИдентификаторыОбъектовВерсийРасширений.СоздатьНаборЗаписей();
		НаборЗаписей.Отбор.ВерсияРасширений.Установить(ВерсияРасширений);
		НаборЗаписей.Прочитать();
		ТаблицаЗаписей = НаборЗаписей.Выгрузить();
		ТаблицаЗаписей.Колонки.Добавить("Удалить", Новый ОписаниеТипов("Булево"));
		ТаблицаЗаписей.ЗаполнитьЗначения(Истина, "Удалить");
		ТаблицаЗаписей.Индексы.Добавить("Идентификатор, ПолноеИмяОбъекта, ВерсияРасширений");
		ОбновитьНаборЗаписей = Ложь;
	КонецЕсли;
	
	Для Каждого Свойства Из Выгрузка Цикл
		
		// Обновление родителей идентификаторов объектов метаданных.
		Если Не Свойства.ЭтоКоллекция Тогда
			СвойстваОбъекта = СвойстваОбъектовМетаданных.Найти(Свойства.ПолноеИмя, "ПолноеИмя");
			НовыйРодитель = ПустаяСсылкаСправочника(ОбъектыРасширений);
			
			Если СвойстваОбъекта <> Неопределено Тогда
				Если Не ЗначениеЗаполнено(СвойстваОбъекта.ПолноеИмяРодителя) Тогда
					// Коллекция объектов метаданных.
					НовыйРодитель = СвойстваОбъекта.Родитель;
				Иначе
					// Не коллекция объектов метаданных, например, подсистема.
					ОписаниеРодителя = Выгрузка.Найти(СвойстваОбъекта.ПолноеИмяРодителя, "ПолноеИмя");
					Если ОписаниеРодителя <> Неопределено Тогда
						НовыйРодитель = ОписаниеРодителя.Ссылка;
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
			
			Если Свойства.Родитель <> НовыйРодитель Тогда
				Свойства.Родитель = НовыйРодитель;
				Свойства.Обновлен = Истина;
			КонецЕсли;
			
			Если ОбъектыРасширений
			   И Свойства.ПометкаУдаления = Ложь
			   И СвойстваРасширений.ИменаНеподключенныхРасширений[НРег(Свойства.ИмяРасширения)] = Неопределено
			   И СвойстваРасширений.ИменаНеподключенныхРасширений[НРег(Свойства.ИдентификаторРасширения)] = Неопределено Тогда
				
				Отбор = Новый Структура;
				Отбор.Вставить("ВерсияРасширений", ВерсияРасширений);
				Отбор.Вставить("Идентификатор",    Свойства.Ссылка);
				Отбор.Вставить("ПолноеИмяОбъекта", Свойства.ПолноеИмя);
				Строки = ТаблицаЗаписей.НайтиСтроки(Отбор);
				Если Строки.Количество() = 0 Тогда
					ОбновитьНаборЗаписей = Истина;
					ЗаполнитьЗначенияСвойств(ТаблицаЗаписей.Добавить(), Отбор);
				Иначе
					Строки[0].Удалить = Ложь;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		
		// Обновление идентификаторов объектов метаданных.
		Если Свойства.ЭтоНовый Тогда
			ТаблицаОбъект = СоздатьЭлементСправочника(ОбъектыРасширений);
			ТаблицаОбъект.УстановитьСсылкуНового(Свойства.Ссылка);
			
		ИначеЕсли Свойства.Обновлен Тогда
			ТаблицаОбъект = Свойства.Ссылка.ПолучитьОбъект();
		Иначе
			Продолжить;
		КонецЕсли;
		
		ЕстьИзменения = Истина;
		Если ТолькоПроверка Тогда
			Возврат;
		КонецЕсли;
		
		ЗаполнитьЗначенияСвойств(ТаблицаОбъект, Свойства);
		ТаблицаОбъект.КлючОбъектаМетаданных = Новый ХранилищеЗначения(Свойства.КлючОбъектаМетаданных);
		ТаблицаОбъект.ОбменДанными.Загрузка = Истина;
		// @skip-check query-in-loop - В вызываемом варианте ветка с запросом не используется
		ПроверитьОбъектПередЗаписью(ТаблицаОбъект, Истина);
		ТаблицаОбъект.Записать();
	КонецЦикла;
	
	Если ОбъектыРасширений Тогда
		ТаблицаЗаписей.Индексы.Добавить("Удалить");
		Строки = ТаблицаЗаписей.НайтиСтроки(Новый Структура("Удалить", Истина));
		Если Строки.Количество() > 0
		   И (Строки.Количество() <> 1
		      Или ЗначениеЗаполнено(Строки[0].ПолноеИмяОбъекта)
		        И Строки[0].ВерсияРасширений = ВерсияРасширений) Тогда
			ОбновитьНаборЗаписей = Истина;
			Для Каждого Строка Из Строки Цикл
				ТаблицаЗаписей.Удалить(Строка);
			КонецЦикла;
		КонецЕсли;
		Если ТаблицаЗаписей.Количество() = 0
		   И ЗначениеЗаполнено(ВерсияРасширений) Тогда
			// Добавление записи, если в расширении нет объектов метаданных,
			// чтобы при проверке наличия кэша, получить значение Истина.
			ТаблицаЗаписей.Добавить().ВерсияРасширений = ВерсияРасширений;
			ОбновитьНаборЗаписей = Истина;
		КонецЕсли;
		Если ОбновитьНаборЗаписей Тогда
			ЕстьИзменения = Истина;
			Если ТолькоПроверка Тогда
				Возврат;
			КонецЕсли;
			НаборЗаписей.Загрузить(ТаблицаЗаписей);
			НаборЗаписей.Записать();
		КонецЕсли;
	КонецЕсли;
	// АПК:1327-вкл.
	
КонецПроцедуры

Процедура ОбновитьСвойстваПомеченногоНаУдаление(Свойства, СвойстваОбновлены = Ложь, ЕстьУдаленные = Ложь, ЭтоДубль = Ложь)
	
	ОбъектыРасширений = ЭтоОбъектРасширений(Свойства.Ссылка);
	
	Если ЭтоДубль Тогда
		КлючОбъектаМетаданных = ?(ТипЗнч(Свойства.КлючОбъектаМетаданных) = Тип("ХранилищеЗначения"),
			Свойства.КлючОбъектаМетаданных.Получить(), Свойства.КлючОбъектаМетаданных);
	КонецЕсли;
	
	Если НЕ Свойства.ПометкаУдаления
	 ИЛИ ЗначениеЗаполнено(Свойства.Родитель)
	 ИЛИ Лев(Свойства.Наименование, 1)  <> "?"
	 ИЛИ Лев(Свойства.Имя, 1)           <> "?"
	 ИЛИ Лев(Свойства.Синоним, 1)       <> "?"
	 ИЛИ Лев(Свойства.ПолноеИмя, 1)     <> "?"
	 ИЛИ Лев(Свойства.ПолныйСиноним, 1) <> "?"
	 ИЛИ ОбъектыРасширений И Лев(Свойства.ИмяРасширения, 1)           <> "?"
	 ИЛИ ОбъектыРасширений И Лев(Свойства.ИдентификаторРасширения, 1) <> "?"
	 ИЛИ ОбъектыРасширений И Лев(Свойства.ХешСуммаРасширения, 1)      <> "?"
	 ИЛИ СтрНайти(Свойства.ПолноеИмя, "(") = 0
	 ИЛИ Свойства.ЗначениеПустойСсылки  <> Неопределено
	 ИЛИ Свойства.ИмяПредопределенныхДанных <> ""
	 ИЛИ ЭтоДубль
	   И КлючОбъектаМетаданных <> Неопределено Тогда
		
		Если НЕ Свойства.ПометкаУдаления Или Лев(Свойства.ПолноеИмя, 1) <> "?" Тогда
			ЕстьУдаленные = Истина;
		КонецЕсли;
		
		// Установка новых свойств идентификатора объекта метаданных.
		Свойства.ПометкаУдаления       = Истина;
		Свойства.Родитель              = ПустаяСсылкаСправочника(ЭтоОбъектРасширений(Свойства.Ссылка));
		Свойства.Наименование          = ВставитьЗнакВопроса(Свойства.Наименование);
		Свойства.Имя                   = ВставитьЗнакВопроса(Свойства.Имя);
		Свойства.Синоним               = ВставитьЗнакВопроса(Свойства.Синоним);
		Свойства.ПолноеИмя             = УникальноеПолноеИмя(Свойства);
		Свойства.ПолныйСиноним         = ВставитьЗнакВопроса(Свойства.ПолныйСиноним);
		Свойства.ЗначениеПустойСсылки  = Неопределено;
		Свойства.ИмяПредопределенныхДанных = "";
		
		Если ОбъектыРасширений Тогда
			Свойства.ИмяРасширения           = ВставитьЗнакВопроса(Свойства.ИмяРасширения);
			Свойства.ИдентификаторРасширения = ВставитьЗнакВопроса(Свойства.ИдентификаторРасширения);
			Свойства.ХешСуммаРасширения      = ВставитьЗнакВопроса(Свойства.ХешСуммаРасширения);
		КонецЕсли;
		
		Если ЭтоДубль Тогда
			Если ТипЗнч(Свойства.КлючОбъектаМетаданных) = Тип("ХранилищеЗначения") Тогда
				Свойства.КлючОбъектаМетаданных = Новый ХранилищеЗначения(Неопределено);
			Иначе
				Свойства.КлючОбъектаМетаданных = Неопределено;
			КонецЕсли;
		КонецЕсли;
		СвойстваОбновлены = Истина;
	КонецЕсли;
	
КонецПроцедуры

Процедура ПроверитьОбновитьСвойстваКоллекции(Знач ТекущиеСвойства, ОбъектыРасширений)
	
	СвойстваКоллекций = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений);
	НовыеСвойства = СвойстваКоллекций.Найти(ТекущиеСвойства.Ссылка.УникальныйИдентификатор(), "Идентификатор");
	
	НаименованиеКоллекции = НовыеСвойства.Синоним;
	
	Если ТекущиеСвойства.Наименование              <> НаименованиеКоллекции
	 ИЛИ ТекущиеСвойства.ПорядокКоллекции          <> НовыеСвойства.ПорядокКоллекции
	 ИЛИ ТекущиеСвойства.Имя                       <> НовыеСвойства.Имя
	 ИЛИ ТекущиеСвойства.Синоним                   <> НовыеСвойства.Синоним
	 ИЛИ ТекущиеСвойства.ПолноеИмя                 <> НовыеСвойства.Имя
	 ИЛИ ТекущиеСвойства.ПолныйСиноним             <> НовыеСвойства.Синоним
	 ИЛИ ТекущиеСвойства.БезДанных                 <> Ложь
	 ИЛИ ТекущиеСвойства.ЗначениеПустойСсылки      <> Неопределено
	 ИЛИ ТекущиеСвойства.ИмяПредопределенныхДанных <> ""
	 ИЛИ ТекущиеСвойства.ПометкаУдаления           <> Ложь
	 ИЛИ ТекущиеСвойства.КлючОбъектаМетаданных     <> Неопределено Тогда
		
		// Установка новых свойств.
		ТекущиеСвойства.Наименование              = НаименованиеКоллекции;
		ТекущиеСвойства.ПорядокКоллекции          = НовыеСвойства.ПорядокКоллекции;
		ТекущиеСвойства.Имя                       = НовыеСвойства.Имя;
		ТекущиеСвойства.Синоним                   = НовыеСвойства.Синоним;
		ТекущиеСвойства.ПолноеИмя                 = НовыеСвойства.Имя;
		ТекущиеСвойства.ПолныйСиноним             = НовыеСвойства.Синоним;
		ТекущиеСвойства.БезДанных                 = Ложь;
		ТекущиеСвойства.ЗначениеПустойСсылки      = Неопределено;
		ТекущиеСвойства.ИмяПредопределенныхДанных = "";
		ТекущиеСвойства.ПометкаУдаления           = Ложь;
		ТекущиеСвойства.КлючОбъектаМетаданных     = Неопределено;
		
		ТекущиеСвойства.Обновлен = Истина;
	КонецЕсли;
	
КонецПроцедуры

// Параметры:
//  ПолноеИмя - Строка
// 
// Возвращаемое значение:
//  - Тип
//  - Строка
//
Функция КлючОбъектаМетаданных(ПолноеИмя)
	
	ПозицияТочки = СтрНайти(ПолноеИмя, ".");
	
	КлассОбъектаМетаданных = ВРег(Лев( ПолноеИмя, ПозицияТочки - 1));
	ИмяОбъектаМетаданных   = Сред(ПолноеИмя, ПозицияТочки + 1);
	
	Если КлассОбъектаМетаданных = ВРег("ПланОбмена") 
		Или КлассОбъектаМетаданных = ВРег("Справочник")
		Или КлассОбъектаМетаданных = ВРег("Документ")
		Или КлассОбъектаМетаданных = ВРег("ПланВидовХарактеристик")
		Или КлассОбъектаМетаданных = ВРег("ПланСчетов")
		Или КлассОбъектаМетаданных = ВРег("ПланВидовРасчета")
		Или КлассОбъектаМетаданных = ВРег("БизнесПроцесс")
		Или КлассОбъектаМетаданных = ВРег("Задача") Тогда
		Возврат Тип(КлассОбъектаМетаданных + "Ссылка." + ИмяОбъектаМетаданных);
		
	ИначеЕсли КлассОбъектаМетаданных = ВРег("Роль") Тогда
		Возврат КлючРоли(Метаданные.Роли[ИмяОбъектаМетаданных]);
		
	ИначеЕсли КлассОбъектаМетаданных = ВРег("Константа")
		Или КлассОбъектаМетаданных = ВРег("ЖурналДокументов") Тогда
		Возврат ТипЗнч(ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПолноеИмя));
		
	ИначеЕсли КлассОбъектаМетаданных = ВРег("Отчет")
		Или КлассОбъектаМетаданных = ВРег("Обработка") Тогда
		Возврат Тип(КлассОбъектаМетаданных + "Объект." + ИмяОбъектаМетаданных);
		
	ИначеЕсли КлассОбъектаМетаданных = ВРег("РегистрСведений")
		Или КлассОбъектаМетаданных = ВРег("РегистрНакопления")
		Или КлассОбъектаМетаданных = ВРег("РегистрБухгалтерии")
		Или КлассОбъектаМетаданных = ВРег("РегистрРасчета") Тогда
		Возврат Тип(КлассОбъектаМетаданных + "КлючЗаписи." + ИмяОбъектаМетаданных);
	Иначе
		// Без ключа объекта метаданных.
		Возврат Тип("Неопределено");
	КонецЕсли;
	
КонецФункции 

Функция КлючиОбъектовМетаданныхСовпадают(Свойства, Объект)
	
	Возврат Свойства.КлючОбъектаМетаданных = Объект.КлючОбъектаМетаданных.Получить();
	
КонецФункции

// Параметры:
//  СвойстваИдентификатора - СтрокаТаблицыЗначений:
//   * ИдентификаторРасширения - Строка
//   * ИмяРасширения - Строка
//   * КлючОбъектаМетаданных - ХранилищеЗначения
//   * ПолноеИмя - Строка
//   * ПолноеИмяКоллекции - Строка
//   * ПометкаУдаления - Булево
//   * Представление - Строка
//   * Ссылка - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//   * ХешСуммаРасширения - Строка
// 
// Возвращаемое значение:
//   Структура:
//     * НеСоответствует            - Булево
//     * КлючОбъектаМетаданных      - Произвольный
//     * ОбъектМетаданных           - ОбъектМетаданных
//     * ОбъектМетаданныхУдаленного - ОбъектМетаданных
//     * ПредставлениеУдаленного    - Строка
//
Функция КлючОбъектаМетаданныхСоответствуетПолномуИмени(СвойстваИдентификатора)
	
	РезультатПроверки = Новый Структура;
	РезультатПроверки.Вставить("НеСоответствует", Истина);
	РезультатПроверки.Вставить("КлючОбъектаМетаданных", Неопределено);
	РезультатПроверки.Вставить("ОбъектМетаданных", Неопределено);
	РезультатПроверки.Вставить("ОбъектМетаданныхУдаленного", Неопределено);
	РезультатПроверки.Вставить("ПредставлениеУдаленного", "");
	
	КлючОбъектаМетаданных = СвойстваИдентификатора.КлючОбъектаМетаданных.Получить();
	ОбъектыРасширений = ЭтоОбъектРасширений(СвойстваИдентификатора.Ссылка);
	
	Если КлючОбъектаМетаданных <> Неопределено
	   И КлючОбъектаМетаданных <> Тип("Неопределено") Тогда
		// Ключ задан, поиск объекта метаданных по ключу.
		РезультатПроверки.КлючОбъектаМетаданных = КлючОбъектаМетаданных;
		ОбъектМетаданных = ОбъектМетаданныхПоКлючу(КлючОбъектаМетаданных,
			СвойстваИдентификатора.ИмяРасширения,
			СвойстваИдентификатора.ИдентификаторРасширения,
			СвойстваИдентификатора.ХешСуммаРасширения);
		Если ОбъектМетаданных <> Неопределено Тогда
			РезультатПроверки.НеСоответствует = ОбъектМетаданных.ПолноеИмя() <> СвойстваИдентификатора.ПолноеИмя;
		КонецЕсли;
	Иначе
		// Ключ не задан, поиск объекта метаданных по полному имени.
		ОбъектМетаданных = МетаданныеНайтиПоПолномуИмени(СвойстваИдентификатора.ПолноеИмя);
		Если ОбъектМетаданных = Неопределено Тогда
			// Возможно задана коллекция
			
			Строка = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений).Найти(
				СвойстваИдентификатора.Ссылка.УникальныйИдентификатор(), "Идентификатор");
			
			Если Строка <> Неопределено Тогда
				ОбъектМетаданных = Метаданные[Строка.Имя];
				РезультатПроверки.НеСоответствует = Строка.Имя <> СвойстваИдентификатора.ПолноеИмяКоллекции;
			КонецЕсли;
		Иначе
			РезультатПроверки.НеСоответствует = Ложь;
		КонецЕсли;
	КонецЕсли;
	
	РезультатПроверки.ОбъектМетаданных = ОбъектМетаданных;
	
	Если ОбъектМетаданных = Неопределено
	   И СвойстваИдентификатора.ПометкаУдаления
	   И СтрНачинаетсяС(СвойстваИдентификатора.ПолноеИмяКоллекции, "? ") Тогда
		
		РезультатПроверки.ОбъектМетаданныхУдаленного = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(
			ПолноеИмяУдаленного(СвойстваИдентификатора.ПолноеИмяКоллекции));
	КонецЕсли;
	Если СтрНачинаетсяС(Строка(СвойстваИдентификатора.Представление), "? ") Тогда
		РезультатПроверки.ПредставлениеУдаленного =
			Сред(Строка(СвойстваИдентификатора.Представление), 3);
	КонецЕсли;
	
	Возврат РезультатПроверки;
	
КонецФункции

Функция ПолноеИмяУдаленного(ПолноеИмя)
	
	ПолноеИмяУдаленного = Сред(ПолноеИмя, 3);
	ПозицияСкобки = СтрНайти(ПолноеИмяУдаленного, "(");
	Если ПозицияСкобки > 0 Тогда
		ПолноеИмяУдаленного = Сред(ПолноеИмяУдаленного, 1, ПозицияСкобки - 1);
	КонецЕсли;
	
	Возврат СокрЛП(ПолноеИмяУдаленного);
	
КонецФункции

Функция ЗапрещеноИзменятьПолноеИмя(Объект)
	
	ОбъектыРасширений = ЭтоОбъектРасширений(Объект);
	Если ЭтоКоллекция(Объект.Ссылка, ОбъектыРасширений) Тогда
		Возврат Истина;
	КонецЕсли;
	
	ПозицияТочки = СтрНайти(Объект.ПолноеИмя, ".");
	ИмяБазовогоТипа = Лев(Объект.ПолноеИмя, ПозицияТочки -1);
	
	СвойстваКоллекций = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений);
	СвойстваКоллекции = СвойстваКоллекций.Найти(ИмяБазовогоТипа, "ИмяВЕдЧисле");
	
	Если СвойстваКоллекции <> Неопределено
	   И НЕ СвойстваКоллекции.БезКлючаОбъектаМетаданных Тогда
		
		Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

Функция ОбъектМетаданныхПоКлючу(КлючОбъектаМетаданных, ИмяРасширения, ИдентификаторРасширения, ХешСуммаРасширения)
	
	ОбъектМетаданных = Неопределено;
	ТипКлючаОбъектаМетаданных = ТипЗнч(КлючОбъектаМетаданных);
	
	Если ТипКлючаОбъектаМетаданных = Тип("Тип") Тогда
		ОбъектМетаданных = Метаданные.НайтиПоТипу(КлючОбъектаМетаданных);
	ИначеЕсли ТипКлючаОбъектаМетаданных = Тип("Строка") Тогда
		ОбъектМетаданных = СтандартныеПодсистемыПовтИсп.РолиПоКлючамОбъектовМетаданных().Получить(КлючОбъектаМетаданных);
	КонецЕсли;
	
	Если ОбъектМетаданных = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	РасширениеОбъекта = ОбъектМетаданных.РасширениеКонфигурации();
	Если РасширениеОбъекта = Неопределено Тогда
		Возврат ?(ЗначениеЗаполнено(ИмяРасширения), Неопределено, ОбъектМетаданных);
	КонецЕсли;
	
	Если НРег(РасширениеОбъекта.УникальныйИдентификатор) = НРег(ИдентификаторРасширения)
	 Или НРег(РасширениеОбъекта.УникальныйИдентификатор) = НРег(Сред(ИдентификаторРасширения, 3))
	 Или НРег(РасширениеОбъекта.Имя) = НРег(ИмяРасширения)
	 Или НРег(РасширениеОбъекта.Имя) = НРег(Сред(ИмяРасширения, 3)) Тогда
		
		Возврат ОбъектМетаданных;
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

// Для вызова из СтандартныеПодсистемыПовтИсп.РолиПоКлючамОбъектовМетаданных.
// 
// Возвращаемое значение:
//  Соответствие из КлючИЗначение:
//   * Ключ - Строка - ключ объекта метаданных Роль
//   * Значение - ОбъектМетаданных - роль
//
Функция РолиПоКлючамОбъектовМетаданных() Экспорт
	
	РолиПоКлючам = Новый Соответствие;
	Для Каждого Роль Из Метаданные.Роли Цикл
		РолиПоКлючам.Вставить(КлючРоли(Роль), Роль);
	КонецЦикла;
	
	Возврат РолиПоКлючам;
	
КонецФункции

Функция КлючРоли(ОбъектМетаданныхРоль)
	
	ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
	ПользовательИБ.Роли.Добавить(ОбъектМетаданныхРоль);
	
	Строка = НРег(СтрЗаменить(ЗначениеВСтрокуВнутр(ПользовательИБ.Роли), Символы.ПС, ""));
	СтрокаПоиска = "{""#"",d6d05c81-8b72-4eef-96d3-f795c1424c29,{1,";
	Позиция = СтрНайти(Строка, СтрокаПоиска);
	Если Позиция = 1 Тогда
		Идентификатор = Сред(Строка, СтрДлина(СтрокаПоиска) + 1, 36);
		Если СтроковыеФункцииКлиентСервер.ЭтоУникальныйИдентификатор(Идентификатор) Тогда
			Возврат Идентификатор;
		КонецЕсли;
	КонецЕсли;
	
	ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Не удалось получить ключ роли %1'"), ОбъектМетаданныхРоль.Имя);
	
	ВызватьИсключение ТекстОшибки;
	
КонецФункции

// Параметры:
//  ОбъектыРасширений - Булево
//  СвойстваКоллекций - см. СвойстваКоллекцийОбъектовМетаданных
//  ИдентификаторыКлючейРасширений - Соответствие
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//   * Наименование         - Строка
//   * ПолноеИмя            - Строка
//   * ПолноеИмяРодителя    - Строка
//   * ПорядокКоллекции     - Число
//   * Родитель             - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//                          - СправочникСсылка.ИдентификаторыОбъектовРасширений
//   * Имя                  - Строка
//   * ИмяПредопределенныхДанных - Строка
//   * Синоним              - Строка
//   * ПолныйСиноним        - Строка
//   * БезДанных            - Булево
//   * БезКлючаОбъектаМетаданных - Булево
//   * ИмяРасширения        - Строка
//   * ИдентификаторРасширения - Строка
//   * ХешСуммаРасширения   - Строка
//   * ЗначениеПустойСсылки - ЛюбаяСсылка
//   * ОбъектМетаданных     - ОбъектМетаданных
//
Функция СвойстваОбъектовМетаданных(ОбъектыРасширений, СвойстваКоллекций = Неопределено, ИдентификаторыКлючейРасширений = Неопределено)
	
	МассивТиповРодителя = Новый Массив;
	МассивТиповРодителя.Добавить(ТипЗнч(ПустаяСсылкаСправочника(ОбъектыРасширений)));
	
	СвойстваОбъектовМетаданных = Новый ТаблицаЗначений;
	СвойстваОбъектовМетаданных.Колонки.Добавить("Наименование",              Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(150)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ПолноеИмя",                 Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(510)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ПолноеИмяРодителя",         Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(510)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ПорядокКоллекции",          Новый ОписаниеТипов("Число"));
	СвойстваОбъектовМетаданных.Колонки.Добавить("Родитель",                  Новый ОписаниеТипов(МассивТиповРодителя));
	СвойстваОбъектовМетаданных.Колонки.Добавить("Имя",                       Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(150)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ИмяПредопределенныхДанных", Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(255)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("Синоним",                   Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(255)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ПолныйСиноним",             Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(510)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("БезДанных",                 Новый ОписаниеТипов("Булево"));
	СвойстваОбъектовМетаданных.Колонки.Добавить("БезКлючаОбъектаМетаданных", Новый ОписаниеТипов("Булево"));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ИмяРасширения",             Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(128)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ИдентификаторРасширения",   Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(38)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ХешСуммаРасширения",        Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(30)));
	СвойстваОбъектовМетаданных.Колонки.Добавить("ЗначениеПустойСсылки");
	СвойстваОбъектовМетаданных.Колонки.Добавить("ОбъектМетаданных");
	
	Если СвойстваКоллекций = Неопределено Тогда
		СвойстваКоллекций = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений);
	КонецЕсли;
	
	Если ОбъектыРасширений И ИдентификаторыКлючейРасширений = Неопределено Тогда
		ИдентификаторыКлючейРасширений = ИдентификаторыКлючейРасширений();
	КонецЕсли;
	
	ИменаПредопределенныхДанных = ?(ОбъектыРасширений,
		Метаданные.Справочники.ИдентификаторыОбъектовРасширений,
		Метаданные.Справочники.ИдентификаторыОбъектовМетаданных).ПолучитьИменаПредопределенных();
	
	ИменаПредопределенных = Новый Соответствие;
	Для Каждого ИмяПредопределенного Из ИменаПредопределенныхДанных Цикл
		ИменаПредопределенных.Вставить(ИмяПредопределенного, Ложь);
	КонецЦикла;
	
	Если Не ОбъектыРасширений Или ЗначениеЗаполнено(ПараметрыСеанса.ПодключенныеРасширения) Тогда
		Для Каждого СвойстваКоллекции Из СвойстваКоллекций Цикл
			ДобавитьСвойстваОбъектовМетаданных(Метаданные[СвойстваКоллекции.Имя], СвойстваКоллекции,
				СвойстваОбъектовМетаданных, ИдентификаторыКлючейРасширений, ИменаПредопределенных);
		КонецЦикла;
		СвойстваОбъектовМетаданных.Индексы.Добавить("ПолноеИмя");
	КонецЕсли;
	
	Возврат СвойстваОбъектовМетаданных;
	
КонецФункции

Процедура ДобавитьСвойстваОбъектовМетаданных(Знач КоллекцияОбъектовМетаданных,
                                             Знач СвойстваКоллекции,
                                             Знач СвойстваОбъектовМетаданных,
                                             Знач ИдентификаторыКлючейРасширений,
                                             Знач ИменаПредопределенных,
                                             Знач ПолноеИмяРодителя = "",
                                             Знач ПолныйСинонимРодителя = "")
	
	
	ОбъектыРасширений = ИдентификаторыКлючейРасширений <> Неопределено;
	
	Для Каждого ОбъектМетаданных Из КоллекцияОбъектовМетаданных Цикл
		
		ПолноеИмя = ОбъектМетаданных.ПолноеИмя();
		Расширение = ОбъектМетаданных.РасширениеКонфигурации();
		ИмяРасширения           = ?(Расширение = Неопределено, "", Расширение.Имя);
		ИдентификаторРасширения = ?(Расширение = Неопределено, "", НРег(Расширение.УникальныйИдентификатор));
		ХешСуммаРасширения      = ?(Расширение = Неопределено, "", Base64Строка(Расширение.ХешСумма));
		Если ОбъектыРасширений И Расширение <> Неопределено Тогда
			КлючРасширения = НРег(ИмяРасширения) + " " + ХешСуммаРасширения;
			НовыйИдентификаторРасширения = ИдентификаторыКлючейРасширений.Получить(КлючРасширения);
			Если НовыйИдентификаторРасширения <> Неопределено
			   И НовыйИдентификаторРасширения <> ИдентификаторРасширения Тогда
				ИдентификаторРасширения = НовыйИдентификаторРасширения;
			КонецЕсли;
		КонецЕсли;
		Если ЗначениеЗаполнено(ИмяРасширения) <> ОбъектыРасширений Тогда
			Продолжить;
		КонецЕсли;
		
		Если СтрНайти(СвойстваКоллекции.ИмяВЕдЧисле, "Подсистема") <> 0 Тогда
			МетаданныеНайтиПоПолномуИмени(ПолноеИмя);
		КонецЕсли;
		
		Если Не СвойстваКоллекции.БезДанных
		   И Не СтандартныеПодсистемыСервер.ЭтоТаблицаРегистра(СвойстваКоллекции.ИмяВЕдЧисле)
		   И СтрНайти(СвойстваКоллекции.ИмяВЕдЧисле, "Константа") = 0 Тогда
			
			ИмяТипаСсылки = СвойстваКоллекции.ИмяВЕдЧисле + "Ссылка." + ОбъектМетаданных.Имя;
			ОписаниеТипа = Новый ОписаниеТипов(ИмяТипаСсылки);
			ЗначениеПустойСсылки = ОписаниеТипа.ПривестиЗначение(Неопределено);
		Иначе
			ЗначениеПустойСсылки = Неопределено;
		КонецЕсли;
		
		НоваяСтрока = СвойстваОбъектовМетаданных.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяСтрока, СвойстваКоллекции);
		НоваяСтрока.Родитель          = ИдентификаторКоллекции(СвойстваКоллекции.Идентификатор, ОбъектыРасширений);
		НоваяСтрока.Наименование      = ПредставлениеОбъектаМетаданных(ОбъектМетаданных, СвойстваКоллекции);
		НоваяСтрока.ПолноеИмя         = ПолноеИмя;
		НоваяСтрока.ПолноеИмяРодителя = ПолноеИмяРодителя;
		НоваяСтрока.Имя               = ОбъектМетаданных.Имя;
		
		НоваяСтрока.Синоним = ?(
			ЗначениеЗаполнено(ОбъектМетаданных.Синоним), ОбъектМетаданных.Синоним, ОбъектМетаданных.Имя);
		
		НоваяСтрока.ПолныйСиноним =
			ПолныйСинонимРодителя + СвойстваКоллекции.СинонимВЕдЧисле + ". " + НоваяСтрока.Синоним;
		
		НоваяСтрока.ЗначениеПустойСсылки    = ЗначениеПустойСсылки;
		НоваяСтрока.ОбъектМетаданных        = ОбъектМетаданных;
		НоваяСтрока.ИмяРасширения           = ИмяРасширения;
		НоваяСтрока.ИдентификаторРасширения = ИдентификаторРасширения;
		НоваяСтрока.ХешСуммаРасширения      = ХешСуммаРасширения;
		
		Если СвойстваКоллекции.Имя = "Подсистемы" Тогда
			ДобавитьСвойстваОбъектовМетаданных(
				ОбъектМетаданных.Подсистемы,
				СвойстваКоллекции,
				СвойстваОбъектовМетаданных,
				ИдентификаторыКлючейРасширений,
				ИменаПредопределенных,
				ПолноеИмя,
				НоваяСтрока.ПолныйСиноним + ". ");
		КонецЕсли;
		ИмяПредопределенного = СтрЗаменить(ПолноеИмя, ".", "");
		Если ИменаПредопределенных.Получить(ИмяПредопределенного) <> Неопределено Тогда
			НоваяСтрока.ИмяПредопределенныхДанных = ИмяПредопределенного;
			ИменаПредопределенных.Вставить(ИмяПредопределенного, Истина);
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

Функция ПредставлениеОбъектаМетаданных(Знач ОбъектМетаданных, Знач СвойстваКоллекции)
	
	Постфикс = "(" + СвойстваКоллекции.СинонимВЕдЧисле + ")";
	
	Синоним = ?(ЗначениеЗаполнено(ОбъектМетаданных.Синоним), ОбъектМетаданных.Синоним, ОбъектМетаданных.Имя);
	
	МаксимальнаяДлинаСинонима = 150 - СтрДлина(Постфикс);
	Если СтрДлина(Синоним) > МаксимальнаяДлинаСинонима + 1 Тогда
		Возврат Лев(Синоним, МаксимальнаяДлинаСинонима - 2) + "..." + Постфикс;
	КонецЕсли;
	
	Возврат Синоним + " (" + СвойстваКоллекции.СинонимВЕдЧисле + ")";
	
КонецФункции

Функция ВставитьЗнакВопроса(Знач Строка)
	
	Если Не СтрНачинаетсяС(Строка, "?") Тогда
		Если Не СтрНачинаетсяС(Строка, " ") Тогда
			Строка = "? " + Строка;
		Иначе
			Строка = "?" + Строка;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Строка;
	
КонецФункции

Функция УникальноеПолноеИмя(Свойства)
	
	ПолноеИмя = ВставитьЗнакВопроса(Свойства.ПолноеИмя);
	
	Если СтрНайти(ПолноеИмя, "(") = 0 Тогда
		ПолноеИмя = ПолноеИмя + " (" + Строка(Свойства.Ссылка.УникальныйИдентификатор())+ ")";
	КонецЕсли;
	
	Возврат ПолноеИмя;
	
КонецФункции

Функция МетаданныеНайтиПоПолномуИмени(ПолноеИмя)
	
	Если СтрНачинаетсяС(ПолноеИмя, "?") Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмя);
	
КонецФункции

Функция ПолноеИмяИспользуется(Объект, ОбъектыРасширения)
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("ПолноеИмя", Объект.ПолноеИмя);
	Запрос.УстановитьПараметр("Ссылка",    Объект.Ссылка);
	Запрос.Текст =
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	ИСТИНА КАК ЗначениеИстина
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных
	|ГДЕ
	|	ИдентификаторыОбъектовМетаданных.Ссылка <> &Ссылка
	|	И ИдентификаторыОбъектовМетаданных.ПолноеИмя = &ПолноеИмя";
	УточнитьИмяСправочникаВТекстеЗапроса(Запрос.Текст, ОбъектыРасширения);
	
	Возврат НЕ Запрос.Выполнить().Пустой();
	
КонецФункции

Функция ЭтоКоллекция(Ссылка, ОбъектыРасширений = Ложь)
	
	СвойстваКоллекций = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений);
	Возврат СвойстваКоллекций.Найти(Ссылка.УникальныйИдентификатор(), "Идентификатор") <> Неопределено;
	
КонецФункции

Процедура ПодготовитьСписокНовыхПодсистемВГлавномУзле(Выгрузка)
	
	НайденноеОписание = Выгрузка.Найти(Метаданные.Подсистемы.СтандартныеПодсистемы, "ОбъектМетаданных");
	Если НайденноеОписание = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Отбор = Новый Структура;
	Отбор.Вставить("ЭтоНовый", Истина);
	НайденныеОписания = Выгрузка.НайтиСтроки(Отбор);
	
	НаследующиеПодсистемы = Новый Массив;
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаСФайлами") Тогда
		МодульРаботаСФайламиСлужебный = ОбщегоНазначения.ОбщийМодуль("РаботаСФайламиСлужебный");
		МодульРаботаСФайламиСлужебный.ПриОпределенииНаследованияПодсистем(Выгрузка, НаследующиеПодсистемы);
	КонецЕсли;
	
	СтрокаПоиска = Метаданные.Подсистемы.СтандартныеПодсистемы.ПолноеИмя() + ".";
	НовыеПодсистемы = Новый Массив;
	ВсеНовыеПодсистемы = Новый Массив;
	Для Каждого Описание Из НайденныеОписания Цикл
		Если НаследующиеПодсистемы.Найти(Описание) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		Если СтрНачинаетсяС(Описание.ПолноеИмя, СтрокаПоиска) Тогда
			НовыеПодсистемы.Добавить(Описание.ПолноеИмя);
		КонецЕсли;
		
		Если СтрНачинаетсяС(Описание.ПолноеИмя, "Подсистема.") Тогда
			ВсеНовыеПодсистемы.Добавить(Описание.ПолноеИмя);
		КонецЕсли;
	КонецЦикла;
	
	ОбновитьСписокНовыхПодсистем(НовыеПодсистемы, ВсеНовыеПодсистемы);
	
КонецПроцедуры

Процедура ПодготовитьСписокНовыхПодсистемВПодчиненномУзле(ОбъектыДляЗаписи)
	
	НовыеПодсистемы = Новый Массив;
	ВсеНовыеПодсистемы = Новый Массив;
	НачалоИмени = "Подсистема.СтандартныеПодсистемы.";
	КлючВсеПодсистемы = "Подсистема.";
	
	Для Каждого Объект Из ОбъектыДляЗаписи Цикл
		Если Не Объект.ЭтоНовый()
			Или Объект.ДополнительныеСвойства.Свойство("ЭтоЗаменаДубля") Тогда
			Продолжить;
		КонецЕсли;
		
		Если ВРег(Лев(Объект.ПолноеИмя, СтрДлина(НачалоИмени))) = ВРег(НачалоИмени) Тогда
			НовыеПодсистемы.Добавить(Объект.ПолноеИмя);
		КонецЕсли;
		
		Если ВРег(Лев(Объект.ПолноеИмя, СтрДлина(КлючВсеПодсистемы))) = ВРег(КлючВсеПодсистемы) Тогда
			ВсеНовыеПодсистемы.Добавить(Объект.ПолноеИмя);
		КонецЕсли;
	КонецЦикла;
	
	ОбновитьСписокНовыхПодсистем(НовыеПодсистемы, ВсеНовыеПодсистемы);
	
КонецПроцедуры

Процедура ОбновитьСписокНовыхПодсистем(НовыеПодсистемы, ВсеНовыеПодсистемы)
	
	Сведения = ОбновлениеИнформационнойБазыСлужебный.СведенияОбОбновленииИнформационнойБазы();
	ЕстьИзменения = Ложь;
	
	Для Каждого ИмяПодсистемы Из НовыеПодсистемы Цикл
		Если Сведения.НовыеПодсистемы.Найти(ИмяПодсистемы) = Неопределено Тогда
			Сведения.НовыеПодсистемы.Добавить(ИмяПодсистемы);
			ЕстьИзменения = Истина;
		КонецЕсли;
	КонецЦикла;
	
	// Удаление из списка подсистем, удаленных из метаданных.
	Индекс = Сведения.НовыеПодсистемы.Количество() - 1;
	Пока Индекс >= 0 Цикл
		ИмяПодсистемы = Сведения.НовыеПодсистемы.Получить(Индекс);
		Если ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ИмяПодсистемы) = Неопределено Тогда
			Сведения.НовыеПодсистемы.Удалить(Индекс);
			ЕстьИзменения = Истина;
		КонецЕсли;
		Индекс = Индекс - 1;
	КонецЦикла;
	
	Если ВсеНовыеПодсистемы <> Неопределено Тогда
		
		Для Каждого ИмяПодсистемы Из ВсеНовыеПодсистемы Цикл
			Если Сведения.ВсеНовыеПодсистемы.Найти(ИмяПодсистемы) = Неопределено Тогда
				Сведения.ВсеНовыеПодсистемы.Добавить(ИмяПодсистемы);
				ЕстьИзменения = Истина;
			КонецЕсли;
		КонецЦикла
		
	КонецЕсли;
	
	Если Не ЕстьИзменения Тогда
		Возврат;
	КонецЕсли;
	
	ОбновлениеИнформационнойБазыСлужебный.ЗаписатьСведенияОбОбновленииИнформационнойБазы(Сведения);
	
КонецПроцедуры

Функция ИдентификаторКоллекции(УникальныйИдентификатор, ОбъектыРасширений)
	
	Если ОбъектыРасширений Тогда
		Возврат Справочники.ИдентификаторыОбъектовРасширений.ПолучитьСсылку(УникальныйИдентификатор);
	Иначе
		Возврат ПолучитьСсылку(УникальныйИдентификатор);
	КонецЕсли;
	
КонецФункции

Функция ЭтоОбъектРасширений(ОбъектИлиСсылка)
	
	Возврат ТипЗнч(ОбъектИлиСсылка) = Тип("СправочникОбъект.ИдентификаторыОбъектовРасширений")
		Или ТипЗнч(ОбъектИлиСсылка) = Тип("СправочникСсылка.ИдентификаторыОбъектовРасширений");
	
КонецФункции

Функция СоздатьЭлементСправочника(ОбъектыРасширений)
	
	Если ОбъектыРасширений Тогда
		Возврат Справочники.ИдентификаторыОбъектовРасширений.СоздатьЭлемент();
	Иначе
		Возврат СоздатьЭлемент();
	КонецЕсли;
	
КонецФункции

Функция ПустаяСсылкаСправочника(ОбъектыРасширений)
	
	Если ОбъектыРасширений Тогда
		Возврат Справочники.ИдентификаторыОбъектовРасширений.ПустаяСсылка();
	Иначе
		Возврат ПустаяСсылка();
	КонецЕсли;
	
КонецФункции

Функция НоваяСсылкаСправочника(ОбъектыРасширений)
	
	Если ОбъектыРасширений Тогда
		Возврат Справочники.ИдентификаторыОбъектовРасширений.ПолучитьСсылку();
	Иначе
		Возврат ПолучитьСсылку();
	КонецЕсли;
	
КонецФункции

Функция ИмяСправочника(ОбъектыРасширений)
	
	Если ОбъектыРасширений Тогда
		Возврат "Справочник.ИдентификаторыОбъектовРасширений";
	Иначе
		Возврат "Справочник.ИдентификаторыОбъектовМетаданных";
	КонецЕсли;
	
КонецФункции

Функция НазваниеСправочника(ОбъектыРасширений)
	
	Если ОбъектыРасширений Тогда
		НазваниеСправочника = НСтр("ru = 'Идентификаторы объектов расширений'");
	Иначе
		НазваниеСправочника = НСтр("ru = 'Идентификаторы объектов метаданных'");
	КонецЕсли;
	
	Возврат НазваниеСправочника;
	
КонецФункции

Процедура УточнитьИмяСправочникаВТекстеЗапроса(ТекстЗапроса, ОбъектыРасширений)
	
	Если ОбъектыРасширений Тогда
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "Справочник.ИдентификаторыОбъектовМетаданных",
			ИмяСправочника(ОбъектыРасширений));
	КонецЕсли;
	
КонецПроцедуры

Процедура ВызватьИсключениеПоОшибке(ОбъектыРасширений, ТекстОшибки)
	
	ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Ошибка при работе со справочником ""%1"".'"),
		НазваниеСправочника(ОбъектыРасширений));
	
	ТекстОшибки = ЗаголовокОшибки + Символы.ПС + Символы.ПС + ТекстОшибки;
	ВызватьИсключение ТекстОшибки;
	
КонецПроцедуры

Функция ЭтоПодсистема(ОбъектМетаданных, КоллекцияПодсистем = Неопределено)
	
	Если КоллекцияПодсистем = Неопределено Тогда
		КоллекцияПодсистем = Метаданные.Подсистемы;
	КонецЕсли;
	
	Если КоллекцияПодсистем.Содержит(ОбъектМетаданных) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Для Каждого Подсистема Из КоллекцияПодсистем Цикл
		Если ЭтоПодсистема(ОбъектМетаданных, Подсистема.Подсистемы) Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Ложь;
	
КонецФункции

// Для процедуры ДобавитьПереименование.
Функция ИмяКоллекции(ПолноеИмя)
	
	ПозицияТочки = СтрНайти(ПолноеИмя, ".");
	
	Если ПозицияТочки > 0 Тогда
		Возврат Лев(ПолноеИмя, ПозицияТочки - 1);
	КонецЕсли;
	
	Возврат "";
	
КонецФункции

// Для процедур ВыполнитьОбновлениеДанных и ПередЗаписьюОбъекта.
Процедура ПроверитьОбъектПередЗаписью(Объект, АвтоматическоеОбновление = Ложь)
	
	ОбъектыРасширений = ЭтоОбъектРасширений(Объект);
	
	Если НЕ АвтоматическоеОбновление Тогда
		
		Если Объект.ЭтоНовый() Тогда
			
			ВызватьИсключениеПоОшибке(ОбъектыРасширений,
				НСтр("ru = 'Создание нового идентификатора объекта
				           |возможно только автоматически при обновлении данных справочника.'"));
				
		ИначеЕсли ЗапрещеноИзменятьПолноеИмя(Объект) Тогда
			
			ВызватьИсключениеПоОшибке(ОбъектыРасширений, СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'При изменении идентификатора объекта указано
				           |полное имя ""%1"", которое может быть
				           |установлено только автоматически при обновлении данных справочника.'"),
				Объект.ПолноеИмя));
		Иначе
			Если ПолноеИмяИспользуется(Объект, Ложь) Тогда
				НазваниеСправочника = НазваниеСправочника(Ложь);
				
			ИначеЕсли ОбъектыРасширений И ПолноеИмяИспользуется(Объект, Истина) Тогда
				НазваниеСправочника = НазваниеСправочника(Истина);
			Иначе
				НазваниеСправочника = "";
			КонецЕсли;
			Если ЗначениеЗаполнено(НазваниеСправочника) Тогда
				ВызватьИсключениеПоОшибке(ОбъектыРасширений, СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'При изменении идентификатора объекта указано
					           |полное имя ""%1"",
					           |которое уже используется в справочнике ""%2"".'"),
					Объект.ПолноеИмя, НазваниеСправочника));
			КонецЕсли;
		КонецЕсли;
		
		ОбновитьСвойстваИдентификатора(Объект);
	КонецЕсли;
	
	Если Не ОбъектыРасширений И ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
		
		Если Объект.ЭтоНовый()
		   И Не ЭтоКоллекция(Объект.ПолучитьСсылкуНового(), ЭтоОбъектРасширений(Объект)) Тогда
			
			ВызватьИсключениеПоОшибке(ОбъектыРасширений,
				НСтр("ru = 'Добавление новых элементов может быть выполнено
				           |только в главном узле распределенной информационной базы.'"));
		КонецЕсли;
		
		Если Не Объект.ПометкаУдаления
		   И Не ЭтоКоллекция(Объект.Ссылка, ЭтоОбъектРасширений(Объект)) Тогда
			
			Если ВРег(Объект.ПолноеИмя) <> ВРег(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.Ссылка, "ПолноеИмя")) Тогда
				ВызватьИсключениеПоОшибке(ОбъектыРасширений,
					НСтр("ru = 'Изменение реквизита ""Полное имя"" может быть выполнено
					           |только в главном узле распределенной информационной базы.'"));
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Для процедур ПроверкаИспользования и ДанныеОбновлены.
Функция ОписаниеОшибкиИдентификаторыОбъектовРасширенийНедоступныВНеразделенномРежиме()
	
	Возврат
		НСтр("ru = 'Справочник ""Идентификаторы объектов расширений""
		           |не может использоваться в неразделенном режиме.'");
	
КонецФункции

// Для процедуры ПриСозданииНаСервереФормыСписка.
Процедура УпорядочитьИОформитьСписок(Форма)
	
	// Порядок.
	Порядок = Форма.Список.КомпоновщикНастроек.Настройки.Порядок;
	Порядок.ИдентификаторПользовательскойНастройки = "ОсновнойПорядок";
	
	Порядок.Элементы.Очистить();
	
	ЭлементПорядка = Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
	ЭлементПорядка.Поле = Новый ПолеКомпоновкиДанных("ПометкаУдаления");
	ЭлементПорядка.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр;
	ЭлементПорядка.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	ЭлементПорядка.Использование = Истина;
	
	ЭлементПорядка = Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
	ЭлементПорядка.Поле = Новый ПолеКомпоновкиДанных("ПорядокКоллекции");
	ЭлементПорядка.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр;
	ЭлементПорядка.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	ЭлементПорядка.Использование = Истина;
	
	ЭлементПорядка = Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
	ЭлементПорядка.Поле = Новый ПолеКомпоновкиДанных("Родитель");
	ЭлементПорядка.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр;
	ЭлементПорядка.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	ЭлементПорядка.Использование = Истина;
	
	ЭлементПорядка = Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
	ЭлементПорядка.Поле = Новый ПолеКомпоновкиДанных("ПометкаБудущегоУдаления");
	ЭлементПорядка.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр;
	ЭлементПорядка.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	ЭлементПорядка.Использование = Истина;
	
	ЭлементПорядка = Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
	ЭлементПорядка.Поле = Новый ПолеКомпоновкиДанных("Синоним");
	ЭлементПорядка.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр;
	ЭлементПорядка.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	ЭлементПорядка.Использование = Истина;
	
	// Оформление.
	ЭлементОформления = Форма.Список.КомпоновщикНастроек.Настройки.УсловноеОформление.Элементы.Добавить();
	ЭлементОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	
	ЭлементЦвета = ЭлементОформления.Оформление.Элементы.Найти("TextColor");
	ЭлементЦвета.Значение = Метаданные.ЭлементыСтиля.ТекстЗапрещеннойЯчейкиЦвет.Значение;
	ЭлементЦвета.Использование = Истина;
	
	ЭлементГруппыОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
	ЭлементГруппыОтбора.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
	
	ЭлементОтбора = ЭлементГруппыОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("ПометкаУдаления");
	ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
	ЭлементОтбора.ПравоеЗначение = Истина;
	ЭлементОтбора.Использование  = Истина;
	
	ЭлементОтбора = ЭлементГруппыОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("ПометкаБудущегоУдаления");
	ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
	ЭлементОтбора.ПравоеЗначение = Истина;
	ЭлементОтбора.Использование  = Истина;
	
КонецПроцедуры

// Для процедуры ОбновитьДанные.
Функция ИменаРасширений(ИсточникРасширений, ИдентификаторыКлючейРасширений)
	
	ИменаРасширений = Новый Соответствие;
	Расширения = РасширенияКонфигурации.Получить(, ИсточникРасширений); // Массив из РасширениеКонфигурации
	
	Для Каждого Расширение Из Расширения Цикл
		ИдентификаторРасширения = НРег(Расширение.УникальныйИдентификатор);
		ИменаРасширений.Вставить(НРег(Расширение.Имя), Расширение.Имя);
		ИменаРасширений.Вставить(ИдентификаторРасширения, Расширение.Имя);
		КлючРасширения = НРег(Расширение.Имя) + " " + Base64Строка(Расширение.ХешСумма);
		НовыйИдентификаторРасширения = ИдентификаторыКлючейРасширений.Получить(КлючРасширения);
		Если НовыйИдентификаторРасширения <> Неопределено
		   И НовыйИдентификаторРасширения <> ИдентификаторРасширения Тогда
			ИменаРасширений.Вставить(НРег(НовыйИдентификаторРасширения), Расширение.Имя);
		КонецЕсли;
	КонецЦикла;
	
	Возврат ИменаРасширений;
	
КонецФункции

// Для процедуры ОбновитьДанные.
Процедура ДополнитьИменаНеподключенныхРасширенийВСеансеБезРазделителей(СвойстваРасширений, РасширенияБазыДанных)
	
	Если Не СтандартныеПодсистемыСервер.ЭтоРазделенныйРежимСеансаБезРазделителей() Тогда
		Возврат;
	КонецЕсли;
	
	ИменаПодключенныхРасширений   = СвойстваРасширений.ИменаПодключенныхРасширений;
	ИменаНеподключенныхРасширений = СвойстваРасширений.ИменаНеподключенныхРасширений;
	
	Для Каждого Расширение Из РасширенияБазыДанных Цикл
		ИдентификаторРасширения = НРег(Расширение.УникальныйИдентификатор);
		ИмяРасширенияДляПоиска = НРег(Расширение.Имя);
		Если ИменаПодключенныхРасширений.Получить(ИдентификаторРасширения) <> Неопределено
		 Или ИменаПодключенныхРасширений.Получить(ИмяРасширенияДляПоиска) <> Неопределено
		 Или ИменаНеподключенныхРасширений.Получить(ИдентификаторРасширения) <> Неопределено
		 Или ИменаНеподключенныхРасширений.Получить(ИмяРасширенияДляПоиска) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		ИменаНеподключенныхРасширений.Вставить(ИмяРасширенияДляПоиска, Расширение.Имя);
		ИменаНеподключенныхРасширений.Вставить(НРег(ИдентификаторРасширения), Расширение.Имя);
	КонецЦикла;
	
КонецПроцедуры

// Для функций ИдентификаторОбъектаМетаданныхПоПолномуИмени, ИдентификаторыОбъектовМетаданных.
Функция ИдентификаторыОбъектовМетаданныхСПопыткойПовтора(ПолныеИменаОбъектовМетаданных, ВызыватьИсключение, ОдинЭлемент)
	
	СтандартныеПодсистемыПовтИсп.ИдентификаторыОбъектовМетаданныхПроверкаИспользования(Истина,
		ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных());
	
	Попытка
		Идентификаторы = ИдентификаторыОбъектовМетаданныхБезПопыткиПовтора(
			ПолныеИменаОбъектовМетаданных, Истина, ОдинЭлемент, Не ВызыватьИсключение);
	Исключение
		Идентификаторы = Неопределено;
	КонецПопытки;
	
	Если Идентификаторы = Неопределено Тогда
		ВыполненоОбновление = ОбновлениеСправочниковИдентификаторов();
		
		Если Не ОбщегоНазначения.РазделениеВключено()
		 Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
			
			Если Не ВыполненоОбновление.ИдентификаторыОбъектовМетаданных Тогда
				ОбновитьДанныеСправочника();
			КонецЕсли;
		КонецЕсли;
		
		Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
			Если Не ВыполненоОбновление.ИдентификаторыОбъектовРасширений Тогда
				Справочники.ИдентификаторыОбъектовРасширений.ОбновитьДанныеСправочника();
			КонецЕсли;
		КонецЕсли;
		
		Идентификаторы = ИдентификаторыОбъектовМетаданныхБезПопыткиПовтора(
			ПолныеИменаОбъектовМетаданных, ВызыватьИсключение, ОдинЭлемент, Не ВызыватьИсключение);
	КонецЕсли;
	
	Возврат Идентификаторы;
	
КонецФункции

// Для функций ИдентификаторыОбъектовМетаданных.
Функция ИдентификаторыОбъектовМетаданныхБезПопыткиПовтора(ПолныеИменаОбъектовМетаданных,
			ВызыватьИсключение, ОдинЭлемент, ПропускатьНеподдерживаемыеОбъекты)
	
	УстановитьПривилегированныйРежим(Истина);
	
	ДоступныИдентификаторыОбъектовРасширений =
		ЗначениеЗаполнено(ПараметрыСеанса.ПодключенныеРасширения)
		И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных();
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("ПолныеИмена", ПолныеИменаОбъектовМетаданных);
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Идентификаторы.Ссылка КАК Ссылка,
	|	Идентификаторы.КлючОбъектаМетаданных КАК КлючОбъектаМетаданных,
	|	Идентификаторы.ПолноеИмя КАК ПолноеИмя,
	|	Идентификаторы.Наименование КАК Представление,
	|	Идентификаторы.ПолноеИмя КАК ПолноеИмяКоллекции,
	|	Идентификаторы.ПометкаУдаления КАК ПометкаУдаления,
	|	"""" КАК ИмяРасширения,
	|	"""" КАК ИдентификаторРасширения,
	|	"""" КАК ХешСуммаРасширения
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовМетаданных КАК Идентификаторы
	|ГДЕ
	|	Идентификаторы.ПолноеИмя В(&ПолныеИмена)
	|	И НЕ Идентификаторы.ПометкаУдаления";
	
	Если ДоступныИдентификаторыОбъектовРасширений Тогда
		Запрос.УстановитьПараметр("ВерсияРасширений", ПараметрыСеанса.ВерсияРасширений);
		ТекстЗапроса =
		"ВЫБРАТЬ
		|	ВерсииИдентификаторов.Идентификатор КАК Ссылка,
		|	Идентификаторы.КлючОбъектаМетаданных КАК КлючОбъектаМетаданных,
		|	ВерсииИдентификаторов.ПолноеИмяОбъекта КАК ПолноеИмя,
		|	Идентификаторы.Наименование КАК Представление,
		|	Идентификаторы.ПолноеИмя КАК ПолноеИмяКоллекции,
		|	Идентификаторы.ПометкаУдаления КАК ПометкаУдаления,
		|	Идентификаторы.ИмяРасширения КАК ИмяРасширения,
		|	Идентификаторы.ИдентификаторРасширения КАК ИдентификаторРасширения,
		|	Идентификаторы.ХешСуммаРасширения КАК ХешСуммаРасширения
		|ИЗ
		|	РегистрСведений.ИдентификаторыОбъектовВерсийРасширений КАК ВерсииИдентификаторов
		|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ИдентификаторыОбъектовРасширений КАК Идентификаторы
		|		ПО (Идентификаторы.Ссылка = ВерсииИдентификаторов.Идентификатор)
		|			И (ВерсииИдентификаторов.ВерсияРасширений = &ВерсияРасширений)
		|ГДЕ
		|	ВерсииИдентификаторов.ПолноеИмяОбъекта В(&ПолныеИмена)";
		
		Запрос.Текст = Запрос.Текст + "
		|
		|ОБЪЕДИНИТЬ ВСЕ
		|
		|" + ТекстЗапроса;
	КонецЕсли;
	
	Выгрузка = Запрос.Выполнить().Выгрузить();
	Выгрузка.Индексы.Добавить("ПолноеИмя");
	
	Ошибки = Новый Массив;
	ДобавитьУточнениеОшибкиПараметровРаботыПрограммыДляРазработчика = Ложь;
	
	КонфигурацияБазыДанныхИзмененаДинамически = КонфигурацияБазыДанныхИзмененаДинамически();
	ИдентификаторыИзКлючей = Неопределено;
	
	Результат = Новый Соответствие;
	Для Каждого ПолноеИмяОбъектаМетаданных Из ПолныеИменаОбъектовМетаданных Цикл
		
		Отбор = Новый Структура("ПолноеИмя", ПолноеИмяОбъектаМетаданных);
		НайденныеСтроки = Выгрузка.НайтиСтроки(Отбор);
		Если НайденныеСтроки.Количество() = 0 Тогда
			// Если идентификатор не найден по полному имени, возможно что полное имя задано с ошибкой.
			ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъектаМетаданных);
			Если ОбъектМетаданных = Неопределено Тогда
				Если Не ВызыватьИсключение Тогда
					Продолжить;
				КонецЕсли;
				ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Объект метаданных с именем ""%1"" не существует.'"),
					ПолноеИмяОбъектаМетаданных);
				Ошибки.Добавить(ОписаниеОшибки);
				Продолжить;
			КонецЕсли;
			
			Если Не Метаданные.Роли.Содержит(ОбъектМетаданных)
			   И Не Метаданные.ПланыОбмена.Содержит(ОбъектМетаданных)
			   И Не Метаданные.Константы.Содержит(ОбъектМетаданных)
			   И Не Метаданные.Справочники.Содержит(ОбъектМетаданных)
			   И Не Метаданные.Документы.Содержит(ОбъектМетаданных)
			   И Не Метаданные.ЖурналыДокументов.Содержит(ОбъектМетаданных)
			   И Не Метаданные.Отчеты.Содержит(ОбъектМетаданных)
			   И Не Метаданные.Обработки.Содержит(ОбъектМетаданных)
			   И Не Метаданные.ПланыВидовХарактеристик.Содержит(ОбъектМетаданных)
			   И Не Метаданные.ПланыСчетов.Содержит(ОбъектМетаданных)
			   И Не Метаданные.ПланыВидовРасчета.Содержит(ОбъектМетаданных)
			   И Не Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных)
			   И Не Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных)
			   И Не Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных)
			   И Не Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных)
			   И Не Метаданные.БизнесПроцессы.Содержит(ОбъектМетаданных)
			   И Не Метаданные.Задачи.Содержит(ОбъектМетаданных)
			   И Не ЭтоПодсистема(ОбъектМетаданных) Тогда
				
				Если ПропускатьНеподдерживаемыеОбъекты Тогда
					Продолжить;
				КонецЕсли;
				ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Объект метаданных не поддерживается:
					           |""%1"".
					           |
					           |Допустимы только типы объектов метаданных перечисленные в комментарии к функции.'"),
					ПолноеИмяОбъектаМетаданных);
				Ошибки.Добавить(ОписаниеОшибки);
				Продолжить;
			КонецЕсли;
			
			Расширение = ОбъектМетаданных.РасширениеКонфигурации();
			Если Расширение <> Неопределено
			   И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
			
				ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Идентификаторы объектов метаданных расширений не поддерживаются в неразделенном режиме.
					           |Невозможно вернуть идентификатор объекта метаданных ""%1""
					           |расширения ""%2"" версии ""%3"".'"),
					ПолноеИмяОбъектаМетаданных, Расширение.Имя, Расширение.Версия);
				Ошибки.Добавить(ОписаниеОшибки);
				Продолжить;
			КонецЕсли;
			
			Если КонфигурацияБазыДанныхИзмененаДинамически Тогда
				Если ИдентификаторыИзКлючей = Неопределено Тогда
					// @skip-check query-in-loop - Вызывается не более одного раза
					ИдентификаторыИзКлючей = ИдентификаторыИзКлючей();
				КонецЕсли;
				Идентификатор = ИдентификаторыИзКлючей.Получить(ПолноеИмяОбъектаМетаданных);
				Если Идентификатор = Неопределено Тогда
					СтандартныеПодсистемыСервер.ПотребоватьПерезапускСеансаПоПричинеДинамическогоОбновленияВерсииПрограммы();
				КонецЕсли;
				Результат.Вставить(ПолноеИмяОбъектаМетаданных, Идентификатор);
				Продолжить;
			КонецЕсли;
			
			ШаблонОшибки = ?(Расширение <> Неопределено,
				НСтр("ru = 'Для объекта метаданных ""%1""
				           |не существует идентификатор в регистре сведений ""Идентификаторы объектов версий расширений"".'"),
				НСтр("ru = 'Для объекта метаданных ""%1""
				           |не существует идентификатор в справочнике ""Идентификаторы объектов метаданных"".'"));
			ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОшибки, ПолноеИмяОбъектаМетаданных);
			ДобавитьУточнениеОшибкиПараметровРаботыПрограммыДляРазработчика = Истина;
			Ошибки.Добавить(ОписаниеОшибки);
			Продолжить;
			
		ИначеЕсли НайденныеСтроки.Количество() > 1 Тогда
			
			ШаблонОшибки = ?(ДоступныИдентификаторыОбъектовРасширений,
				НСтр("ru = 'Для объекта метаданных ""%1""
				           |найдено несколько идентификаторов в справочнике ""Идентификаторы объектов метаданных"" и
				           |регистре сведений ""Идентификаторы объектов версий расширений"".'"),
				НСтр("ru = 'Для объекта метаданных ""%1""
				           |найдено несколько идентификаторов в справочнике ""Идентификаторы объектов метаданных"".'"));
			ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОшибки, ПолноеИмяОбъектаМетаданных);
			ДобавитьУточнениеОшибкиПараметровРаботыПрограммыДляРазработчика = Истина;
			Ошибки.Добавить(ОписаниеОшибки);
			Продолжить;
			
		КонецЕсли;
		
		// Проверка соответствия ключа объекта метаданных полному имени объекта метаданных.
		СтрокаТаблицы = НайденныеСтроки[0];
		РезультатПроверки = КлючОбъектаМетаданныхСоответствуетПолномуИмени(СтрокаТаблицы);
		Если РезультатПроверки.НеСоответствует Тогда
			НазваниеСправочника = НазваниеСправочника(ЭтоОбъектРасширений(СтрокаТаблицы.Ссылка));
			
			Если РезультатПроверки.ОбъектМетаданных = Неопределено Тогда
				ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Для объекта метаданных ""%1""
					           |найден идентификатор в справочнике ""%2"",
					           |которому соответствует удаленный объект метаданных.'"),
					ПолноеИмяОбъектаМетаданных, НазваниеСправочника);
			Иначе
				ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Для объекта метаданных ""%1""
					           |найден идентификатор в справочнике ""%2"",
					           |который соответствует другому объекту метаданных ""%3"".'"),
					ПолноеИмяОбъектаМетаданных, НазваниеСправочника, РезультатПроверки.ОбъектМетаданных);
			КонецЕсли;
			
			ДобавитьУточнениеОшибкиПараметровРаботыПрограммыДляРазработчика = Истина;
			Ошибки.Добавить(ОписаниеОшибки);
			Продолжить;
		КонецЕсли;
		
		Результат.Вставить(ПолноеИмяОбъектаМетаданных, СтрокаТаблицы.Ссылка);
	КонецЦикла;
	
	КоличествоОшибок = Ошибки.Количество();
	Если КоличествоОшибок > 0 Тогда
		
		Если ОдинЭлемент Тогда
			ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Ошибка при выполнении функции %1.'"),
				"ОбщегоНазначения.ИдентификаторОбъектаМетаданных");
			
		ИначеЕсли КоличествоОшибок = 1 Тогда
			ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Ошибка при выполнении функции %1.'"),
				"ОбщегоНазначения.ИдентификаторыОбъектовМетаданных");
		Иначе
			ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Ошибки при выполнении функции %1.'"),
				"ОбщегоНазначения.ИдентификаторыОбъектовМетаданных");
		КонецЕсли;
		
		Разделитель = Символы.ПС + Символы.ПС;
		ТекстВсехОшибок = "";
		НомерОшибки = 0;
		Для Каждого ОписаниеОшибки Из Ошибки Цикл
			НомерОшибки = НомерОшибки + 1;
			ТекстВсехОшибок = ТекстВсехОшибок + ?(НомерОшибки = 1, "", Разделитель) + ОписаниеОшибки;
			Если НомерОшибки = 3 И КоличествоОшибок > 5 Тогда
				
				ОписаниеОшибки = "... " + СтроковыеФункцииКлиентСервер.СтрокаСЧисломДляЛюбогоЯзыка(
					НСтр("ru = ';И еще %1 ошибка;;И еще %1 ошибки;И еще %1 ошибок;И еще %1 ошибки'"),
					(КоличествоОшибок - НомерОшибки));
				
				ТекстВсехОшибок = ТекстВсехОшибок + Разделитель + ОписаниеОшибки;
				Прервать;
			КонецЕсли;
		КонецЦикла;
		
		ТекстВсехОшибок = ТекстВсехОшибок + ?(ДобавитьУточнениеОшибкиПараметровРаботыПрограммыДляРазработчика,
			СтандартныеПодсистемыСервер.УточнениеОшибкиПараметровРаботыПрограммыДляРазработчика(), "");
		
		ТекстОшибки = ЗаголовокОшибки + Разделитель + ТекстВсехОшибок;
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Для функции ИдентификаторыОбъектовМетаданныхБезПопыткиПовтора.
Функция ИдентификаторыИзКлючей()
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Идентификаторы.Ссылка КАК Ссылка,
	|	Идентификаторы.КлючОбъектаМетаданных КАК ХранилищеКлюча
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовМетаданных КАК Идентификаторы";
	
	Выборка = Запрос.Выполнить().Выбрать();
	
	ИдентификаторыИзКлючей = Новый Соответствие;
	
	Пока Выборка.Следующий() Цикл
		Если ТипЗнч(Выборка.ХранилищеКлюча) <> Тип("ХранилищеЗначения") Тогда
			Продолжить;
		КонецЕсли;
		КлючОбъектаМетаданных = Выборка.ХранилищеКлюча.Получить();
		
		Если КлючОбъектаМетаданных = Неопределено
		 Или КлючОбъектаМетаданных = Тип("Неопределено") Тогда
			Продолжить;
		КонецЕсли;
		
		ОбъектМетаданных = ОбъектМетаданныхПоКлючу(КлючОбъектаМетаданных, "", "", "");
		Если ОбъектМетаданных = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		ПолноеИмя = ОбъектМетаданных.ПолноеИмя();
		Если ИдентификаторыИзКлючей.Получить(ПолноеИмя) <> Неопределено Тогда
			СтандартныеПодсистемыСервер.ПотребоватьПерезапускСеансаПоПричинеДинамическогоОбновленияВерсииПрограммы();
		КонецЕсли;
		
		ИдентификаторыИзКлючей.Вставить(ПолноеИмя, Выборка.Ссылка);
	КонецЦикла;
	
	Возврат ИдентификаторыИзКлючей;
	
КонецФункции

// Для функций ИдентификаторыОбъектовМетаданныхСПопыткойПовтора,
// ОбъектыМетаданныхПоИдентификаторамСПопыткойПовтора.
//
Функция ОбновлениеСправочниковИдентификаторов()
	
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);
	
	Результат = ПараметрыСеанса.ОбновлениеСправочниковИдентификаторов;
	
	УстановитьПривилегированныйРежим(Ложь);
	УстановитьОтключениеБезопасногоРежима(Ложь);
	
	Возврат Результат;
	
КонецФункции

// Для функций ОбъектМетаданныхПоИдентификатору, ОбъектыМетаданныхПоИдентификаторам.
Функция ОбъектыМетаданныхПоИдентификаторамСПопыткойПовтора(Идентификаторы, ВызыватьИсключение)
	
	Если Идентификаторы.Количество() = 0 Тогда
		Возврат Новый Соответствие;
	КонецЕсли;
	
	ИдентификаторыКонфигурации = Новый Массив;
	ИдентификаторыРасширений   = Новый Массив;
	
	ДобавленныеИдентификаторыКонфигурации = Новый Соответствие;
	ДобавленныеИдентификаторыРасширений   = Новый Соответствие;
	
	Обработанные = Новый Соответствие;
	
	Для Каждого ТекущийИдентификатор Из Идентификаторы Цикл
		Если ТипЗнч(ТекущийИдентификатор) = Тип("СправочникСсылка.ИдентификаторыОбъектовМетаданных")
		   И ЗначениеЗаполнено(ТекущийИдентификатор) Тогда
			
			Если ДобавленныеИдентификаторыКонфигурации[ТекущийИдентификатор] = Неопределено Тогда
				ИдентификаторыКонфигурации.Добавить(ТекущийИдентификатор);
				ДобавленныеИдентификаторыКонфигурации.Вставить(ТекущийИдентификатор, Истина);
			КонецЕсли;
		
		ИначеЕсли ТипЗнч(ТекущийИдентификатор) = Тип("СправочникСсылка.ИдентификаторыОбъектовРасширений")
		   И ЗначениеЗаполнено(ТекущийИдентификатор) Тогда
			
			Если ДобавленныеИдентификаторыРасширений[ТекущийИдентификатор] = Неопределено Тогда
				ИдентификаторыРасширений.Добавить(ТекущийИдентификатор);
				ДобавленныеИдентификаторыРасширений.Вставить(ТекущийИдентификатор, Истина);
			КонецЕсли;
		ИначеЕсли ВызыватьИсключение Тогда
			Если ТипЗнч(ТекущийИдентификатор) = Тип("СправочникСсылка.ИдентификаторыОбъектовМетаданных")
			 Или ТипЗнч(ТекущийИдентификатор) = Тип("СправочникСсылка.ИдентификаторыОбъектовРасширений") Тогда
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка при выполнении функции %1.
					           |
					           |Неверный идентификатор: пустая ссылка типа ""%2"".'"),
					"ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору",
					ТипЗнч(ТекущийИдентификатор));
			Иначе
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка при выполнении функции %1.
					           |
					           |Неверный тип идентификатора объекта метаданных:
					           |""%2"".'"),
					"ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору",
					ТипЗнч(ТекущийИдентификатор));
			КонецЕсли;
			ВызватьИсключение ТекстОшибки;
		Иначе
			Обработанные.Вставить(ТекущийИдентификатор, Null);
		КонецЕсли;
	КонецЦикла;
	
	Если ИдентификаторыКонфигурации.Количество() > 0 Тогда
		СтандартныеПодсистемыПовтИсп.ИдентификаторыОбъектовМетаданныхПроверкаИспользования(Истина, Ложь);
	КонецЕсли;
	
	Если ИдентификаторыРасширений.Количество() > 0 Тогда
		СтандартныеПодсистемыПовтИсп.ИдентификаторыОбъектовМетаданныхПроверкаИспользования(Истина, Истина);
	КонецЕсли;
	
	Если ИдентификаторыКонфигурации.Количество() > 0 Или ИдентификаторыРасширений.Количество() > 0 Тогда
		Попытка
			ОбъектыМетаданных = ОбъектыМетаданныхПоИдентификаторамБезПопыткиПовтора(Идентификаторы,
				ИдентификаторыКонфигурации, ИдентификаторыРасширений, ВызыватьИсключение);
		Исключение
			Если Не ОбщегоНазначения.РазделениеВключено()
			 Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
				// В случае ошибки, если есть возможность обновления справочника,
				// нужно выполнить обновление, а после этого повторить получение идентификатора.
				ОбъектыМетаданных = Неопределено;
			Иначе
				ВызватьИсключение;
			КонецЕсли;
		КонецПопытки;
	Иначе
		ОбъектыМетаданных = Новый Соответствие;
	КонецЕсли;
	
	Если ОбъектыМетаданных = Неопределено Тогда
		ВыполненоОбновление = ОбновлениеСправочниковИдентификаторов();
		Если Не ВыполненоОбновление.ИдентификаторыОбъектовМетаданных Тогда
			ОбновитьДанныеСправочника();
		КонецЕсли;
		ОбъектыМетаданных = ОбъектыМетаданныхПоИдентификаторамБезПопыткиПовтора(Идентификаторы,
			ИдентификаторыКонфигурации, ИдентификаторыРасширений, ВызыватьИсключение);
	КонецЕсли;
	
	Для Каждого КлючИЗначение Из Обработанные Цикл
		ОбъектыМетаданных.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
	КонецЦикла;
	
	Возврат ОбъектыМетаданных;
	
КонецФункции

// Для функции ОбъектыМетаданныхПоИдентификаторамСПопыткойПовтора.
Функция ОбъектыМетаданныхПоИдентификаторамБезПопыткиПовтора(Идентификаторы,
			ИдентификаторыКонфигурации, ИдентификаторыРасширений, ВызыватьИсключение)
	
	УстановитьПривилегированныйРежим(Истина);
	
	Запрос = Новый Запрос;
	
	Если ИдентификаторыКонфигурации.Количество() > 0 Тогда
		Запрос.УстановитьПараметр("ИдентификаторыКонфигурации", ИдентификаторыКонфигурации);
		Запрос.Текст =
		"ВЫБРАТЬ
		|	Идентификаторы.Ссылка КАК Ссылка,
		|	Идентификаторы.КлючОбъектаМетаданных КАК КлючОбъектаМетаданных,
		|	Идентификаторы.ПолноеИмя КАК ПолноеИмя,
		|	Идентификаторы.Наименование КАК Представление,
		|	Идентификаторы.ПолноеИмя КАК ПолноеИмяКоллекции,
		|	Идентификаторы.ПометкаУдаления КАК ПометкаУдаления,
		|	ЛОЖЬ КАК ОбъектРасширений,
		|	"""" КАК ИмяРасширения,
		|	"""" КАК ИдентификаторРасширения,
		|	"""" КАК ХешСуммаРасширения
		|ИЗ
		|	Справочник.ИдентификаторыОбъектовМетаданных КАК Идентификаторы
		|ГДЕ
		|	Идентификаторы.Ссылка В(&ИдентификаторыКонфигурации)";
	КонецЕсли;
	
	Если ИдентификаторыРасширений.Количество() > 0 Тогда
		Запрос.УстановитьПараметр("ИдентификаторыРасширений", ИдентификаторыРасширений);
		Запрос.УстановитьПараметр("ВерсияРасширений", ПараметрыСеанса.ВерсияРасширений);
		Если ЗначениеЗаполнено(Запрос.Текст) Тогда
			Запрос.Текст = Запрос.Текст +
			"
			|
			|ОБЪЕДИНИТЬ ВСЕ
			|
			|";
		КонецЕсли;
		Запрос.Текст = Запрос.Текст +
		"ВЫБРАТЬ
		|	Идентификаторы.Ссылка КАК Ссылка,
		|	Идентификаторы.КлючОбъектаМетаданных КАК КлючОбъектаМетаданных,
		|	ЕСТЬNULL(ВерсииИдентификаторов.ПолноеИмяОбъекта, """") КАК ПолноеИмя,
		|	Идентификаторы.Наименование КАК Представление,
		|	Идентификаторы.ПолноеИмя КАК ПолноеИмяКоллекции,
		|	Идентификаторы.ПометкаУдаления КАК ПометкаУдаления,
		|	ИСТИНА КАК ОбъектРасширений,
		|	Идентификаторы.ИмяРасширения КАК ИмяРасширения,
		|	Идентификаторы.ИдентификаторРасширения КАК ИдентификаторРасширения,
		|	Идентификаторы.ХешСуммаРасширения КАК ХешСуммаРасширения
		|ИЗ
		|	Справочник.ИдентификаторыОбъектовРасширений КАК Идентификаторы
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИдентификаторыОбъектовВерсийРасширений КАК ВерсииИдентификаторов
		|		ПО (ВерсииИдентификаторов.Идентификатор = Идентификаторы.Ссылка)
		|			И (ВерсииИдентификаторов.ВерсияРасширений = &ВерсияРасширений)
		|ГДЕ
		|	Идентификаторы.Ссылка В(&ИдентификаторыРасширений)";
	КонецЕсли;
	
	Выгрузка = Запрос.Выполнить().Выгрузить();
	ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Ошибка при выполнении функции %1.'"),
		"ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору");
	
	ОбъектыМетаданныхИдентификаторов = Новый Соответствие;
	
	ВсегоИдентификаторов = ИдентификаторыКонфигурации.Количество() + ИдентификаторыРасширений.Количество();
	Если Выгрузка.Количество() < ВсегоИдентификаторов Тогда
		Для Каждого Идентификатор Из Идентификаторы Цикл
			Если Выгрузка.Найти(Идентификатор, "Ссылка") = Неопределено Тогда
				Если ВызыватьИсключение Тогда
					Прервать;
				Иначе
					// Объект метаданных не существует.
					ОбъектыМетаданныхИдентификаторов.Вставить(Идентификатор, Null);
					Продолжить;
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		Если ВызыватьИсключение Тогда
			Если ИдентификаторыРасширений.Найти(Идентификатор) = Неопределено Тогда
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Идентификатор объекта метаданных ""%1""
					           |был удален из информационной базы после того, как был помечен на удаление
					           |в связи с тем, что объект был удален из новой версии конфигурации.
					           |
					           |Все настройки, сделанные для объекта до его удаления
					           |более недоступны, их следует удалить. Если позже объект
					           |был вновь добавлен, тогда настройки следует сделать заново.'"),
					Строка(Идентификатор));
			Иначе
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Идентификатор объекта расширений ""%1""
					           |был удален из информационной базы после того, как был помечен на удаление
					           |в связи с тем, что было удалено расширение конфигурации с этим объектом
					           |или объект был удален из новой версии расширения конфигурации.
					           |
					           |Все настройки, сделанные для объекта до его удаления
					           |более недоступны, их следует удалить. Если позже объект
					           |был вновь добавлен, тогда настройки следует сделать заново.'"),
					Строка(Идентификатор));
			КонецЕсли;
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
	КонецЕсли;
	
	КонфигурацияБазыДанныхИзмененаДинамически = КонфигурацияБазыДанныхИзмененаДинамически();
	
	// Проверка соответствия ключа объекта метаданных полному имени объекта метаданных.
	Для Каждого Свойства Из Выгрузка Цикл
		РезультатПроверки = КлючОбъектаМетаданныхСоответствуетПолномуИмени(Свойства);
		Если РезультатПроверки.НеСоответствует Тогда
			
			Если РезультатПроверки.ОбъектМетаданных = Неопределено Тогда
				Если ЗначениеЗаполнено(РезультатПроверки.ПредставлениеУдаленного) Тогда
					ПредставлениеИдентификатора = РезультатПроверки.ПредставлениеУдаленного;
				Иначе
					ПредставлениеИдентификатора = Свойства.Представление;
				КонецЕсли;
				
				Если Свойства.ОбъектРасширений Тогда
					ОбъектРасширенияНеСуществует = Свойства.ПометкаУдаления;
					ИмяРасширения = "";
					ИдентификаторРасширения = ?(СтрНачинаетсяС(Свойства.ИдентификаторРасширения, "? "),
						Сред(Свойства.ИдентификаторРасширения, 3), Свойства.ИдентификаторРасширения);
					Если СтроковыеФункцииКлиентСервер.ЭтоУникальныйИдентификатор(ИдентификаторРасширения) Тогда
						Отбор = Новый Структура("УникальныйИдентификатор", Новый УникальныйИдентификатор(ИдентификаторРасширения));
						УстановленныеРасширения = РасширенияКонфигурации.Получить(Отбор, ИсточникРасширенийКонфигурации.БазаДанных);
						ОтключенныеРасширения   = РасширенияКонфигурации.Получить(Отбор, ИсточникРасширенийКонфигурации.СеансОтключенные);
						АктивныеРасширения      = РасширенияКонфигурации.Получить(Отбор, ИсточникРасширенийКонфигурации.СеансАктивные);
						Если АктивныеРасширения.Количество() > 0 
							Или ОтключенныеРасширения.Количество() > 0 
							Или УстановленныеРасширения.Количество() > 0 Тогда
							ИмяРасширения = УстановленныеРасширения[0].Имя;
						КонецЕсли;
					КонецЕсли;
					Если Не ЗначениеЗаполнено(ИмяРасширения) Тогда
						ИмяРасширения = ?(СтрНачинаетсяС(Свойства.ИмяРасширения, "? "),
							Сред(Свойства.ИмяРасширения, 3), Свойства.ИмяРасширения);
						Отбор = Новый Структура("Имя", ИмяРасширения);
						УстановленныеРасширения = РасширенияКонфигурации.Получить(Отбор, ИсточникРасширенийКонфигурации.БазаДанных);
						ОтключенныеРасширения   = РасширенияКонфигурации.Получить(Отбор, ИсточникРасширенийКонфигурации.СеансОтключенные);
						АктивныеРасширения      = РасширенияКонфигурации.Получить(Отбор, ИсточникРасширенийКонфигурации.СеансАктивные);
					КонецЕсли;
					Если УстановленныеРасширения.Количество() = 0 Тогда
						ОбъектРасширенияНеСуществует = Истина;
						ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
							НСтр("ru = 'Расширение конфигурации ""%1"" удалено.
							           |Объект ""%2"" не существует.
							           |Все настройки, сделанные для расширения до его удаления, более недоступны.
							           |Следует выполнить настройки заново с учетом изменений.'"),
							ИмяРасширения,
							ПредставлениеИдентификатора);
						
					ИначеЕсли Не УстановленныеРасширения[0].Активно Тогда
						ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
							НСтр("ru = 'Расширение конфигурации ""%1"" установлено, но выключено.
							           |Включите расширение и перезапустите сеанс.'"),
							ИмяРасширения);
						
					ИначеЕсли ОтключенныеРасширения.Количество() > 0 И Не ОтключенныеРасширения[0].Активно
					      Или ОтключенныеРасширения.Количество() = 0 И АктивныеРасширения.Количество() = 0 Тогда
						
						ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
							НСтр("ru = 'Расширение конфигурации ""%1"" установлено после запуска сеанса, поэтому не подключено.
							           |Перезапустите сеанс.'"),
							ИмяРасширения);
						
					ИначеЕсли ОтключенныеРасширения.Количество() > 0 И ОтключенныеРасширения[0].Активно Тогда
						ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
							НСтр("ru = 'Расширение конфигурации ""%1"" установлено, но отключено при запуске сеанса.
							           |Это значит, что при его подключении возникла ошибка.'"),
							ИмяРасширения);
						
					Иначе // АктивныеРасширения.Количество() > 0
						ОбъектРасширенияНеСуществует = Истина;
						
						Если РезультатПроверки.ОбъектМетаданныхУдаленного <> Неопределено
						   И РезультатПроверки.ОбъектМетаданныхУдаленного.РасширениеКонфигурации() <> Неопределено
						   И РезультатПроверки.ОбъектМетаданныхУдаленного.РасширениеКонфигурации().Имя = АктивныеРасширения[0].Имя Тогда
							
							ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
								НСтр("ru = 'Расширение конфигурации ""%1"" установлено и подключено,
								           |но объект ""%2""
								           |не может быть получен по идентификатору помеченному на удаление.
								           |Обычно это значит, что расширение было удалено и установлено заново вместо обновления,
								           |поэтому все настройки, сделанные для расширения до его удаления,
								           |более недоступны и их следует сделать заново.'"),
								ИмяРасширения,
								ПредставлениеИдентификатора);
						Иначе
							ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
								НСтр("ru = 'Расширение конфигурации ""%1"" установлено и подключено,
								           |но объект ""%2"" не существует.
								           |Это значит, что объект был удален в новой версии расширения.
								           |Объект и все настройки, сделанные до его удаления, более недоступны.
								           |Следует выполнить настройки заново с учетом изменений.'"),
								ИмяРасширения,
								ПредставлениеИдентификатора);
						КонецЕсли;
					КонецЕсли;
					
					Если ВызыватьИсключение Тогда
						ВызватьИсключение ТекстОшибки;
						
					ИначеЕсли ОбъектРасширенияНеСуществует Тогда
						ОбъектыМетаданныхИдентификаторов.Вставить(Свойства.Ссылка, Null);
					Иначе
						ОбъектыМетаданныхИдентификаторов.Вставить(Свойства.Ссылка, Неопределено);
						Продолжить;
					КонецЕсли;
					
				ИначеЕсли КонфигурацияБазыДанныхИзмененаДинамически Тогда
					// Возможно объект метаданных будет доступен после перезапуска.
					Если ВызыватьИсключение Тогда
						// Стандартное исключение по причине динамического обновления.
						СтандартныеПодсистемыСервер.ПотребоватьПерезапускСеансаПоПричинеДинамическогоОбновленияВерсииПрограммы();
					Иначе
						ОбъектыМетаданныхИдентификаторов.Вставить(Свойства.Ссылка, Неопределено);
						Продолжить;
					КонецЕсли;
					
				ИначеЕсли Не ВызыватьИсключение Тогда
					// Объект метаданных не существует.
					ОбъектыМетаданныхИдентификаторов.Вставить(Свойства.Ссылка, Null);
					Продолжить;
					
				ИначеЕсли РезультатПроверки.ОбъектМетаданныхУдаленного <> Неопределено
				        И РезультатПроверки.ОбъектМетаданныхУдаленного.РасширениеКонфигурации() = Неопределено Тогда
					
					ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
						НСтр("ru = 'Объект ""%1""
						           |не может быть получен по идентификатору помеченному на удаление.
						           |Это значит, что объект был удален из конфигурации, а позже снова добавлен.
						           |Поэтому все настройки, сделанные для объекта до его удаления
						           |более недоступны и их следует сделать заново.'"),
						ПредставлениеИдентификатора);
					ВызватьИсключение ТекстОшибки;
				Иначе
					ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
						НСтр("ru = 'Объект ""%1"" не существует.
						           |Это значит, что объект метаданных был удален в новой версии конфигурации.
						           |Объект и все настройки, сделанные до его удаления, более недоступны.
						           |Следует выполнить настройки заново с учетом изменений.'"),
						ПредставлениеИдентификатора);
					ВызватьИсключение ТекстОшибки;
				КонецЕсли;
				
			ИначеЕсли КонфигурацияБазыДанныхИзмененаДинамически Тогда
				// Возможно объект метаданных был переименован.
				ОписаниеОшибки = "";
			Иначе
				ОписаниеОшибки =  СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Идентификатору ""%1""
					           |найденному в справочнике ""%2"",
					           |соответствует объект метаданных ""%3"",
					           |полное имя которого отличается от заданного в идентификаторе.'"),
					Свойства.Представление,
					НазваниеСправочника(Свойства.ОбъектРасширений),
					РезультатПроверки.ОбъектМетаданных.ПолноеИмя())
					+ СтандартныеПодсистемыСервер.УточнениеОшибкиПараметровРаботыПрограммыДляРазработчика();
			КонецЕсли;
			
			Если ЗначениеЗаполнено(ОписаниеОшибки) Тогда
				ТекстОшибки = ЗаголовокОшибки + Символы.ПС + Символы.ПС + ОписаниеОшибки;
				ВызватьИсключение ТекстОшибки;
			КонецЕсли;
		КонецЕсли;
		
		Если Не Свойства.ОбъектРасширений И Свойства.ПометкаУдаления И Не КонфигурацияБазыДанныхИзмененаДинамически Тогда
			ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Идентификатор ""%1""
				           |найден в справочнике ""%2"",
				           |но значение реквизита ""Пометка удаления"" установлено Истина.'"),
				Свойства.Представление,
				НазваниеСправочника(Свойства.ОбъектРасширений));
			
			ТекстОшибки = ЗаголовокОшибки + Символы.ПС + Символы.ПС + ОписаниеОшибки
				+ СтандартныеПодсистемыСервер.УточнениеОшибкиПараметровРаботыПрограммыДляРазработчика();
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
		
		ОписаниеОбъектаМетаданных = Новый Структура("Объект, Ключ, ПолноеИмя", РезультатПроверки.ОбъектМетаданных);
		Если РезультатПроверки.КлючОбъектаМетаданных <> Неопределено Тогда
			ОписаниеОбъектаМетаданных.Ключ = РезультатПроверки.КлючОбъектаМетаданных;
		Иначе
			ОписаниеОбъектаМетаданных.Ключ      = Свойства.ПолноеИмя;
			ОписаниеОбъектаМетаданных.ПолноеИмя = Свойства.ПолноеИмя;
		КонецЕсли;
		ОбъектыМетаданныхИдентификаторов.Вставить(Свойства.Ссылка, ОписаниеОбъектаМетаданных);
	КонецЦикла;
	
	Возврат ОбъектыМетаданныхИдентификаторов;
	
КонецФункции

// Для функций ОбъектыМетаданныхПоИдентификаторам, ИдентификаторыОбъектовМетаданных.
Функция КэшИдентификаторов()
	
	КлючДанныхПовторногоИспользования = Строка(ПараметрыСеанса.КлючДанныхПовторногоИспользования);
	
	Возврат СтандартныеПодсистемыПовтИсп.КэшИдентификаторовОбъектовМетаданных(КлючДанныхПовторногоИспользования);
	
КонецФункции

// Для вызова из СтандартныеПодсистемыПовтИсп.КэшИдентификаторовОбъектовМетаданных.
// 
// Параметры:
//  КлючДанныхПовторногоИспользования - УникальныйИдентификатор
//
// Возвращаемое значение:
//  Структура:
//   * ИдентификаторыПоПолнымИменам - Соответствие
//   * ОписаниеОбъектовМетаданныхПоИдентификаторам - Соответствие
//
Функция КэшИдентификаторовОбъектовМетаданных(КлючДанныхПовторногоИспользования) Экспорт
	
	Хранилище = Новый Структура;
	Хранилище.Вставить("ИдентификаторыПоПолнымИменам", Новый Соответствие);
	Хранилище.Вставить("ОписаниеОбъектовМетаданныхПоИдентификаторам", Новый Соответствие);
	
	Возврат Новый ФиксированнаяСтруктура(Хранилище);
	
КонецФункции

// Для вызова из СтандартныеПодсистемыПовтИсп.ПредставлениеИдентификатораОбъектаМетаданных.
// Используется из процедуры ОбработкаПолученияПредставления.
// 
// Параметры:
//  Ссылка - СправочникСсылка.ИдентификаторыОбъектовМетаданных
//         - СправочникСсылка.ИдентификаторыОбъектовРасширений
//
// Возвращаемое значение:
//  Строка
//
Функция ПредставлениеИдентификатора(Ссылка) Экспорт
	
	ОбъектыРасширений = ТипЗнч(Ссылка) <> Тип("СправочникСсылка.ИдентификаторыОбъектовМетаданных");
	СвойстваКоллекций = СтандартныеПодсистемыПовтИсп.СвойстваКоллекцийОбъектовМетаданных(ОбъектыРасширений);
	
	СвойстваКоллекции = СвойстваКоллекций.Найти(Ссылка.УникальныйИдентификатор(), "Идентификатор");
	Если СвойстваКоллекции <> Неопределено Тогда
		Возврат СвойстваКоллекции.Синоним;
	КонецЕсли;
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Ссылка", Ссылка);
	
	Если ОбъектыРасширений Тогда
		Запрос.УстановитьПараметр("ВерсияРасширений", ПараметрыСеанса.ВерсияРасширений);
		Запрос.Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ЕСТЬNULL(ИдентификаторыОбъектовВерсийРасширений.ПолноеИмяОбъекта, ИдентификаторыОбъектовРасширений.ПолноеИмя) КАК ПолноеИмя
		|ИЗ
		|	Справочник.ИдентификаторыОбъектовРасширений КАК ИдентификаторыОбъектовРасширений
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИдентификаторыОбъектовВерсийРасширений КАК ИдентификаторыОбъектовВерсийРасширений
		|		ПО (ИдентификаторыОбъектовВерсийРасширений.Идентификатор = ИдентификаторыОбъектовРасширений.Ссылка)
		|			И (ИдентификаторыОбъектовВерсийРасширений.ВерсияРасширений = &ВерсияРасширений)
		|ГДЕ
		|	ИдентификаторыОбъектовРасширений.Ссылка = &Ссылка";
	Иначе
		Запрос.Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ИдентификаторыОбъектовМетаданных.ПолноеИмя КАК ПолноеИмя
		|ИЗ
		|	Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных
		|ГДЕ
		|	ИдентификаторыОбъектовМетаданных.Ссылка = &Ссылка";
	КонецЕсли;
	
	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		ПолноеИмя = Выборка.ПолноеИмя;
	Иначе
		ПолноеИмя = Неопределено;
	КонецЕсли;
	
	Если ПолноеИмя = Неопределено Тогда
		Возврат НСтр("ru = 'Объект не существует.'");
	КонецЕсли;
	
	Если СтрНачинаетсяС(ПолноеИмя, "?") Тогда
		Возврат "? " + СтрРазделить(ПолноеИмя, " ")[1];
	КонецЕсли;
	
	ПозицияТочки = СтрНайти(ПолноеИмя, ".");
	ИмяБазовогоТипа = Лев(ПолноеИмя, ПозицияТочки -1);
	
	Отбор = Новый Структура("ИмяВЕдЧисле", ИмяБазовогоТипа);
	Строки = СвойстваКоллекций.НайтиСтроки(Отбор);
	
	Если Строки.Количество() <> 1 Тогда
		Возврат ПолноеИмя;
	КонецЕсли;
	
	ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмя);
	Если ОбъектМетаданных = Неопределено Тогда
		Возврат ПолноеИмя;
	КонецЕсли;
	
	Возврат ПредставлениеОбъектаМетаданных(ОбъектМетаданных, Строки[0]);
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции замены идентификатора в базе данных.

Процедура ЗаменитьДублиПодчиненногоУзлаНайденныеПриЗагрузке(ТолькоПроверка, ЕстьИзменения)
	
	Если ОбщегоНазначения.РазделениеВключено() Тогда
		// В модели сервиса не поддерживается.
		Возврат;
	КонецЕсли;
	
	Если НЕ ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
		Возврат;
	КонецЕсли;
	
	// Замена дублей в подчиненном РИБ-узле.
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Идентификаторы.Ссылка,
	|	Идентификаторы.НоваяСсылка
	|ИЗ
	|	Справочник.ИдентификаторыОбъектовМетаданных КАК Идентификаторы
	|ГДЕ
	|	Идентификаторы.НоваяСсылка <> ЗНАЧЕНИЕ(Справочник.ИдентификаторыОбъектовМетаданных.ПустаяСсылка)";
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Если РезультатЗапроса.Пустой() Тогда
		Возврат;
	КонецЕсли;
	
	Если ТолькоПроверка Тогда
		ЕстьИзменения = Истина;
		Возврат;
	КонецЕсли;
	
	Выборка = РезультатЗапроса.Выбрать();
	ЗаменяемыеСсылки = Новый Массив;
	СтарыеИНовыеСсылки = Новый Соответствие;
	Пока Выборка.Следующий() Цикл
		ЗаменяемыеСсылки.Добавить(Выборка.Ссылка);
		СтарыеИНовыеСсылки.Вставить(Выборка.Ссылка, Выборка.НоваяСсылка);
	КонецЦикла;
	
	ТекущаяПопытка = 1;
	Пока Истина Цикл
		НайденныеДанные = НайтиПоСсылкам(ЗаменяемыеСсылки);
		НайденныеДанные.Колонки[0].Имя = "Ссылка";
		НайденныеДанные.Колонки[1].Имя = "Данные";
		НайденныеДанные.Колонки[2].Имя = "Метаданные";
		НайденныеДанные.Колонки.Добавить("Включено");
		НайденныеДанные.ЗаполнитьЗначения(Истина, "Включено");
		
		Если НайденныеДанные.Количество() = 0 Тогда
			Блокировка = Новый БлокировкаДанных;
			ЭлементБлокировки = Блокировка.Добавить("Справочник.ИдентификаторыОбъектовМетаданных");
			Для Каждого ЗаменяемаяСсылка Из ЗаменяемыеСсылки Цикл
				ЭлементБлокировки.УстановитьЗначение("Ссылка", ЗаменяемаяСсылка);
			КонецЦикла;
			НачатьТранзакцию();
			Попытка
				Блокировка.Заблокировать();
				// Очистка новых ссылок у дублей идентификаторов.
				Для Каждого ЗаменяемаяСсылка Из ЗаменяемыеСсылки Цикл
					ОбъектДубля = ЗаменяемаяСсылка.ПолучитьОбъект();
					ОбъектДубля.НоваяСсылка = Неопределено;
					ОбъектДубля.ОбменДанными.Загрузка = Истина;
					ОбъектДубля.Записать();
				КонецЦикла;
				ЗафиксироватьТранзакцию();
			Исключение
				ОтменитьТранзакцию();
				ВызватьИсключение;
			КонецПопытки;
			Прервать;
		КонецЕсли;
		
		Если ТекущаяПопытка > 10 Тогда
			ТекстОшибки =
				НСтр("ru = 'Не удалось выполнить замену дублей идентификаторов объектов метаданных.
				           |После 10 попыток все еще имеются данные, которые требуют замены.
				           |Выполните действие в монопольном режиме.'");
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
		
		БезОшибок = ВыполнитьЗаменуЭлементов(СтарыеИНовыеСсылки, НайденныеДанные, Истина);
		Если Не БезОшибок Тогда
			ТекстОшибки =
				НСтр("ru = 'Не удалось выполнить замену дублей идентификаторов объектов метаданных.
				           |Подробнее см. ошибки при замене идентификатора в журнале регистрации.'");
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
		ТекущаяПопытка = ТекущаяПопытка + 1;
	КонецЦикла;
	
КонецПроцедуры

// Функция из универсальной обработки ПоискИЗаменаЗначений.
// Изменения:
// - удалена работа с формой прогрессора;
// - удалена процедура ОбработкаПрерыванияПользователя;
// - заменено "РегистрыСведений[СтрокаТаблицы.Метаданные.Имя]" на
//   "ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(СтрокаТаблицы.Метаданные.ПолноеИмя())".
//
Функция ВыполнитьЗаменуЭлементов(Знач Заменяемые, Знач ТаблицаСсылок, Знач ОтключатьКонтрольЗаписи = Ложь, Знач ОбъектыРасширений = Ложь)
	
	// АПК:1327-выкл - №783.1.4.1 Во-первых, нетранзакционная операция, так как может быть длительной.
	// Во-вторых, выполняется после загрузки данных из главного узла в режиме обновление информационной базы.
	// В третьих, выполняется только тогда, когда найдены дубли идентификаторов объектов метаданных (редкий случай).
	Параметры = ПараметрыЗаменыЭлементов();
	
	Для Каждого РегистрБухгалтерии Из Метаданные.РегистрыБухгалтерии Цикл
		Параметры.Вставить(РегистрБухгалтерии.Имя + "Субконто",        РегистрБухгалтерии.ПланСчетов.МаксКоличествоСубконто);
		Параметры.Вставить(РегистрБухгалтерии.Имя + "Корреспонденция", РегистрБухгалтерии.Корреспонденция);
	КонецЦикла;
	
	ОбрабатываемаяСсылка = Неопределено;
	БылиИсключения = Ложь;
	
	Попытка
		Для Каждого СтрокаТаблицы Из ТаблицаСсылок Цикл
			Если Не СтрокаТаблицы.Включено Тогда
				Продолжить;
			КонецЕсли;
			ПравильныйЭлемент = Заменяемые[СтрокаТаблицы.Ссылка];
			
			Ссылка = СтрокаТаблицы.Ссылка;
			
			Если ОбрабатываемаяСсылка <> СтрокаТаблицы.Данные Тогда
				Если ОбрабатываемаяСсылка <> Неопределено И Параметры.Объект <> Неопределено Тогда
					
					Попытка
						Параметры.Объект.ОбменДанными.Загрузка = Истина;
						Если ОтключатьКонтрольЗаписи Тогда
							Параметры.Объект.ДополнительныеСвойства.Вставить("ПропуститьЗаписьВерсииОбъекта");
							ОбновлениеИнформационнойБазы.ЗаписатьДанные(Параметры.Объект, Ложь);
						Иначе
							Параметры.Объект.Записать();
						КонецЕсли;
					Исключение
						БылиИсключения = Истина;
						ИнформацияОбОшибке = ИнформацияОбОшибке();
						ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
							НСтр("ru = 'При записи объекта ""%1"" возникла ошибка:
							           |%2'"),
							ПолучитьНавигационнуюСсылку(Параметры.Объект.Ссылка),
							ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
						Если ТранзакцияАктивна() Тогда
							ВызватьИсключение ТекстОшибки;
						КонецЕсли;
						СообщитьОбОшибке(ТекстОшибки, ОбъектыРасширений);
					КонецПопытки;
					Параметры.Объект = Неопределено;
				КонецЕсли;
				ОбрабатываемаяСсылка = СтрокаТаблицы.Данные;
			КонецЕсли;
			
			Если Метаданные.Документы.Содержит(СтрокаТаблицы.Метаданные) Тогда
				
				Если Параметры.Объект = Неопределено Тогда
					Параметры.Объект = СтрокаТаблицы.Данные.ПолучитьОбъект();
				КонецЕсли;
				
				Для Каждого Реквизит Из СтрокаТаблицы.Метаданные.Реквизиты Цикл
					Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) И Параметры.Объект[Реквизит.Имя] = Ссылка Тогда
						Параметры.Объект[Реквизит.Имя] = ПравильныйЭлемент;
					КонецЕсли;
				КонецЦикла;
					
				Для Каждого ТабличнаяЧасть Из СтрокаТаблицы.Метаданные.ТабличныеЧасти Цикл
					Для Каждого Реквизит Из ТабличнаяЧасть.Реквизиты Цикл
						Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) Тогда
							СтрокаТабличнойЧасти = Параметры.Объект[ТабличнаяЧасть.Имя].Найти(Ссылка, Реквизит.Имя);
							Пока СтрокаТабличнойЧасти <> Неопределено Цикл
								СтрокаТабличнойЧасти[Реквизит.Имя] = ПравильныйЭлемент;
								СтрокаТабличнойЧасти = Параметры.Объект[ТабличнаяЧасть.Имя].Найти(Ссылка, Реквизит.Имя);
							КонецЦикла;
						КонецЕсли;
					КонецЦикла;
				КонецЦикла;
				
				Для Каждого Движение Из СтрокаТаблицы.Метаданные.Движения Цикл
					
					ЭтоДвижениеРегистраБухгалтерии = Метаданные.РегистрыБухгалтерии.Содержит(Движение);
					ЕстьКорреспонденция = ЭтоДвижениеРегистраБухгалтерии И Параметры[Движение.Имя + "Корреспонденция"];
					
					НаборЗаписей = Параметры.Объект.Движения[Движение.Имя];
					НаборЗаписей.Прочитать();
					НадоЗаписывать = Ложь;
					ТаблицаНабора = НаборЗаписей.Выгрузить();
					
					Если ТаблицаНабора.Количество() = 0 Тогда
						Продолжить;
					КонецЕсли;
					
					ИменаКолонок = Новый Массив;
					
					// Получим имена измерений, которые могут содержать ссылку.
					Для Каждого Измерение Из Движение.Измерения Цикл
						
						Если Измерение.Тип.СодержитТип(ТипЗнч(Ссылка)) Тогда
							
							Если ЭтоДвижениеРегистраБухгалтерии Тогда
								
								Если Измерение.ПризнакУчета <> Неопределено Тогда
									
									ИменаКолонок.Добавить(Измерение.Имя + "Дт");
									ИменаКолонок.Добавить(Измерение.Имя + "Кт");
								Иначе
									ИменаКолонок.Добавить(Измерение.Имя);
								КонецЕсли;
							Иначе
								ИменаКолонок.Добавить(Измерение.Имя);
							КонецЕсли;
						КонецЕсли;
					КонецЦикла;
					
					// Получим имена ресурсов, которые могут содержать ссылку.
					Если Метаданные.РегистрыСведений.Содержит(Движение) Тогда
						Для Каждого Ресурс Из Движение.Ресурсы Цикл
							Если Ресурс.Тип.СодержитТип(ТипЗнч(Ссылка)) Тогда
								ИменаКолонок.Добавить(Ресурс.Имя);
							КонецЕсли;
						КонецЦикла;
					КонецЕсли;
					
					// Получим имена ресурсов, которые могут содержать ссылку.
					Для Каждого Реквизит Из Движение.Реквизиты Цикл
						Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) Тогда
							ИменаКолонок.Добавить(Реквизит.Имя);
						КонецЕсли;
					КонецЦикла;
					
					// Произведем замены в таблице.
					Для Каждого ИмяКолонки Из ИменаКолонок Цикл
						СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, ИмяКолонки);
						Пока СтрокаТабЧасти <> Неопределено Цикл
							СтрокаТабЧасти[ИмяКолонки] = ПравильныйЭлемент;
							НадоЗаписывать = Истина;
							СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, ИмяКолонки);
						КонецЦикла;
					КонецЦикла;
					
					Если Метаданные.РегистрыБухгалтерии.Содержит(Движение) Тогда
						
						Для ИндексСубконто = 1 По Параметры[Движение.Имя + "Субконто"] Цикл
							Если ЕстьКорреспонденция Тогда
								СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, "СубконтоДт"+ИндексСубконто);
								Пока СтрокаТабЧасти <> Неопределено Цикл
									СтрокаТабЧасти["СубконтоДт"+ИндексСубконто] = ПравильныйЭлемент;
									НадоЗаписывать = Истина;
									СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, "СубконтоДт"+ИндексСубконто);
								КонецЦикла;
								СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, "СубконтоКт"+ИндексСубконто);
								Пока СтрокаТабЧасти <> Неопределено Цикл
									СтрокаТабЧасти["СубконтоКт"+ИндексСубконто] = ПравильныйЭлемент;
									НадоЗаписывать = Истина;
									СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, "СубконтоКт"+ИндексСубконто);
								КонецЦикла;
							Иначе
								СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, "Субконто"+ИндексСубконто);
								Пока СтрокаТабЧасти <> Неопределено Цикл
									СтрокаТабЧасти["Субконто"+ИндексСубконто] = ПравильныйЭлемент;
									НадоЗаписывать = Истина;
									СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, "Субконто"+ИндексСубконто);
								КонецЦикла;
							КонецЕсли;
						КонецЦикла;
						
						Если Ссылка.Метаданные() = Движение.ПланСчетов Тогда
							Для Каждого СтрокаТабЧасти Из ТаблицаНабора Цикл
								Если ЕстьКорреспонденция Тогда
									Если СтрокаТабЧасти.СчетДт = Ссылка Тогда
										СтрокаТабЧасти.СчетДт = ПравильныйЭлемент;
										НадоЗаписывать = Истина;
									КонецЕсли;
									Если СтрокаТабЧасти.СчетКт = Ссылка Тогда
										СтрокаТабЧасти.СчетКт = ПравильныйЭлемент;
										НадоЗаписывать = Истина;
									КонецЕсли;
								Иначе
									Если СтрокаТабЧасти.Счет = Ссылка Тогда
										СтрокаТабЧасти.Счет = ПравильныйЭлемент;
										НадоЗаписывать = Истина;
									КонецЕсли;
								КонецЕсли;
							КонецЦикла;
						КонецЕсли;
					КонецЕсли;
					
					Если Метаданные.РегистрыРасчета.Содержит(Движение) Тогда
						СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, "ВидРасчета");
						Пока СтрокаТабЧасти <> Неопределено Цикл
							СтрокаТабЧасти["ВидРасчета"] = ПравильныйЭлемент;
							НадоЗаписывать = Истина;
							СтрокаТабЧасти = ТаблицаНабора.Найти(Ссылка, "ВидРасчета");
						КонецЦикла;
					КонецЕсли;
					
					Если НадоЗаписывать Тогда
						НаборЗаписей.Загрузить(ТаблицаНабора);
						Попытка
							Если ОтключатьКонтрольЗаписи Тогда
								НаборЗаписей.ДополнительныеСвойства.Вставить("ПропуститьЗаписьВерсииОбъекта");
								ОбновлениеИнформационнойБазы.ЗаписатьДанные(НаборЗаписей, Ложь);
							Иначе
								НаборЗаписей.Записать();
							КонецЕсли;
						Исключение
							БылиИсключения = Истина;
							ИнформацияОбОшибке = ИнформацияОбОшибке();
							ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
								НСтр("ru = 'При записи движений объекта ""%1"" в ""%2"" возникла ошибка:
								           |%3'"),
								ПолучитьНавигационнуюСсылку(Параметры.Объект.Ссылка),
								НаборЗаписей.Метаданные().ПолноеИмя(),
								ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
							Если ТранзакцияАктивна() Тогда
								ВызватьИсключение ТекстОшибки;
							КонецЕсли;
							СообщитьОбОшибке(ТекстОшибки, ОбъектыРасширений);
						КонецПопытки;
					КонецЕсли;
				КонецЦикла;
				
				Для Каждого Последовательность Из Метаданные.Последовательности Цикл
					Если Последовательность.Документы.Содержит(СтрокаТаблицы.Метаданные) Тогда
						НадоЗаписывать = Ложь;
						НаборЗаписи = Последовательности[Последовательность.Имя].СоздатьНаборЗаписей(); // ПоследовательностьНаборЗаписей 
						НаборЗаписи.Отбор.Регистратор.Установить(СтрокаТаблицы.Данные);
						НаборЗаписи.Прочитать();
						
						Если НаборЗаписи.Количество() > 0 Тогда
							Для Каждого Измерение Из Последовательность.Измерения Цикл
								Если Измерение.Тип.СодержитТип(ТипЗнч(Ссылка)) И НаборЗаписи[0][Измерение.Имя]=Ссылка Тогда
									НаборЗаписи[0][Измерение.Имя] = ПравильныйЭлемент;
									НадоЗаписывать = Истина;
								КонецЕсли;
							КонецЦикла;
							Если НадоЗаписывать Тогда
								Попытка
									Если ОтключатьКонтрольЗаписи Тогда
										НаборЗаписи.ДополнительныеСвойства.Вставить("ПропуститьЗаписьВерсииОбъекта");
										ОбновлениеИнформационнойБазы.ЗаписатьДанные(НаборЗаписи, Ложь);
									Иначе
										НаборЗаписи.Записать();
									КонецЕсли;
								Исключение
									БылиИсключения = Истина;
									ИнформацияОбОшибке = ИнформацияОбОшибке();
									ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
											НСтр("ru = 'При записи по регистратору ""%1"" в ""%2"" возникла ошибка:
											           |%3'"),
											ПолучитьНавигационнуюСсылку(СтрокаТаблицы.Данные),
											НаборЗаписи.Метаданные().ПолноеИмя(),
											ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
									Если ТранзакцияАктивна() Тогда
										ВызватьИсключение ТекстОшибки;
									КонецЕсли;
									СообщитьОбОшибке(ТекстОшибки, ОбъектыРасширений);
								КонецПопытки;
							КонецЕсли;
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
				
			ИначеЕсли Метаданные.Справочники.Содержит(СтрокаТаблицы.Метаданные) Тогда
				
				Если Параметры.Объект = Неопределено Тогда
					Параметры.Объект = СтрокаТаблицы.Данные.ПолучитьОбъект();
				КонецЕсли;
				
				Если СтрокаТаблицы.Метаданные.Владельцы.Содержит(Ссылка.Метаданные()) И Параметры.Объект.Владелец = Ссылка Тогда
					Параметры.Объект.Владелец = ПравильныйЭлемент;
				КонецЕсли;
				
				Если СтрокаТаблицы.Метаданные.Иерархический И Параметры.Объект.Родитель = Ссылка Тогда
					Параметры.Объект.Родитель = ПравильныйЭлемент;
				КонецЕсли;
				
				Для Каждого Реквизит Из СтрокаТаблицы.Метаданные.Реквизиты Цикл
					Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) И Параметры.Объект[Реквизит.Имя] = Ссылка Тогда
						Параметры.Объект[Реквизит.Имя] = ПравильныйЭлемент;
					КонецЕсли;
				КонецЦикла;
				
				Для Каждого ТЧ Из СтрокаТаблицы.Метаданные.ТабличныеЧасти Цикл
					Для Каждого Реквизит Из ТЧ.Реквизиты Цикл
						Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) Тогда
							СтрокаТабЧасти = Параметры.Объект[ТЧ.Имя].Найти(Ссылка, Реквизит.Имя);
							Пока СтрокаТабЧасти <> Неопределено Цикл
								СтрокаТабЧасти[Реквизит.Имя] = ПравильныйЭлемент;
								СтрокаТабЧасти = Параметры.Объект[ТЧ.Имя].Найти(Ссылка, Реквизит.Имя);
							КонецЦикла;
						КонецЕсли;
					КонецЦикла;
				КонецЦикла;
				
			ИначеЕсли Метаданные.ПланыВидовХарактеристик.Содержит(СтрокаТаблицы.Метаданные)
			      ИЛИ Метаданные.ПланыСчетов.Содержит            (СтрокаТаблицы.Метаданные)
			      ИЛИ Метаданные.ПланыВидовРасчета.Содержит      (СтрокаТаблицы.Метаданные)
			      ИЛИ Метаданные.Задачи.Содержит                 (СтрокаТаблицы.Метаданные)
			      ИЛИ Метаданные.БизнесПроцессы.Содержит         (СтрокаТаблицы.Метаданные) Тогда
				
				Если Параметры.Объект = Неопределено Тогда
					Параметры.Объект = СтрокаТаблицы.Данные.ПолучитьОбъект();
				КонецЕсли;
				
				Для Каждого Реквизит Из СтрокаТаблицы.Метаданные.Реквизиты Цикл
					Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) И Параметры.Объект[Реквизит.Имя] = Ссылка Тогда
						Параметры.Объект[Реквизит.Имя] = ПравильныйЭлемент;
					КонецЕсли;
				КонецЦикла;
				
				Для Каждого ТЧ Из СтрокаТаблицы.Метаданные.ТабличныеЧасти Цикл
					Для Каждого Реквизит Из ТЧ.Реквизиты Цикл
						Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) Тогда
							СтрокаТабЧасти = Параметры.Объект[ТЧ.Имя].Найти(Ссылка, Реквизит.Имя);
							Пока СтрокаТабЧасти <> Неопределено Цикл
								СтрокаТабЧасти[Реквизит.Имя] = ПравильныйЭлемент;
								СтрокаТабЧасти = Параметры.Объект[ТЧ.Имя].Найти(Ссылка, Реквизит.Имя);
							КонецЦикла;
						КонецЕсли;
					КонецЦикла;
				КонецЦикла;
				
			ИначеЕсли Метаданные.Константы.Содержит(СтрокаТаблицы.Метаданные) Тогда
				
				ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(
					СтрокаТаблицы.Метаданные.ПолноеИмя()).Установить(ПравильныйЭлемент);
				
			ИначеЕсли Метаданные.РегистрыСведений.Содержит(СтрокаТаблицы.Метаданные) Тогда
				
				СтруктураИзмерений = Новый Структура;
				МенеджерРегистра = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(СтрокаТаблицы.Метаданные.ПолноеИмя());
				НаборЗаписей = МенеджерРегистра.СоздатьНаборЗаписей(); // РегистрСведенийНаборЗаписей
				Для Каждого Измерение Из СтрокаТаблицы.Метаданные.Измерения Цикл
					НаборЗаписей.Отбор[Измерение.Имя].Установить(СтрокаТаблицы.Данные[Измерение.Имя]);
					СтруктураИзмерений.Вставить(Измерение.Имя, СтрокаТаблицы.Данные[Измерение.Имя]);
				КонецЦикла;
				Если СтрокаТаблицы.Метаданные.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический Тогда
					НаборЗаписей.Отбор["Период"].Установить(СтрокаТаблицы.Данные.Период);
				КонецЕсли;
				НаборЗаписей.Прочитать();
				
				Если НаборЗаписей.Количество() = 0 Тогда
					Продолжить;
				КонецЕсли;
				
				ТаблицаНабора = НаборЗаписей.Выгрузить();
				НаборЗаписей.Очистить();
				
				ТекстОшибки = "";
				НачатьТранзакцию();
				Попытка
					Попытка
						Если ОтключатьКонтрольЗаписи Тогда
							НаборЗаписей.ДополнительныеСвойства.Вставить("ПропуститьЗаписьВерсииОбъекта");
							ОбновлениеИнформационнойБазы.ЗаписатьДанные(НаборЗаписей, Ложь);
						Иначе
							НаборЗаписей.Записать();
						КонецЕсли;
					Исключение
						ИнформацияОбОшибке = ИнформацияОбОшибке();
						ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
							НСтр("ru = 'При удалении записи ""%1"" возникла ошибка:
							           |%2'"),
							ПолучитьНавигационнуюСсылку(МенеджерРегистра.СоздатьКлючЗаписи(СтруктураИзмерений)),
							ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
						ВызватьИсключение;
					КонецПопытки;
					
					Для Каждого Колонка Из ТаблицаНабора.Колонки Цикл
						Если ТаблицаНабора[0][Колонка.Имя] = Ссылка Тогда
							ТаблицаНабора[0][Колонка.Имя] = ПравильныйЭлемент;
							Если СтруктураИзмерений.Свойство(Колонка.Имя) Тогда
								НаборЗаписей.Отбор[Колонка.Имя].Установить(ПравильныйЭлемент);
								СтруктураИзмерений[Колонка.Имя] = ПравильныйЭлемент;
							КонецЕсли;
						КонецЕсли;
					КонецЦикла;
					
					НаборЗаписей.Загрузить(ТаблицаНабора);
					
					Попытка
						Если ОтключатьКонтрольЗаписи Тогда
							НаборЗаписей.ДополнительныеСвойства.Вставить("ПропуститьЗаписьВерсииОбъекта");
							ОбновлениеИнформационнойБазы.ЗаписатьДанные(НаборЗаписей, Ложь);
						Иначе
							НаборЗаписей.Записать();
						КонецЕсли;
					Исключение
						ИнформацияОбОшибке = ИнформацияОбОшибке();
						ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
							НСтр("ru = 'При добавлении записи ""%1"" возникла ошибка:
							           |%2'"),
							ПолучитьНавигационнуюСсылку(МенеджерРегистра.СоздатьКлючЗаписи(СтруктураИзмерений)),
							ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
						ВызватьИсключение;
					КонецПопытки;
					
					ЗафиксироватьТранзакцию();
				Исключение
					ОтменитьТранзакцию();
					БылиИсключения = Истина;
					Если Не ЗначениеЗаполнено(ТекстОшибки) Тогда
						ВызватьИсключение;
					КонецЕсли;
					Если ТранзакцияАктивна() Тогда
						ВызватьИсключение ТекстОшибки;
					КонецЕсли;
					СообщитьОбОшибке(ТекстОшибки, ОбъектыРасширений);
				КонецПопытки;
			Иначе
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Значения не заменяются в данных типа: %1'"),
					Строка(СтрокаТаблицы.Метаданные));
					
				СообщитьОбОшибке(ТекстОшибки, ОбъектыРасширений);
			КонецЕсли;
		КонецЦикла;
	
		Если Параметры.Объект <> Неопределено Тогда
			Попытка
				Если ОтключатьКонтрольЗаписи Тогда
					Параметры.Объект.ДополнительныеСвойства.Вставить("ПропуститьЗаписьВерсииОбъекта");
					ОбновлениеИнформационнойБазы.ЗаписатьДанные(Параметры.Объект, Ложь);
				Иначе
					Параметры.Объект.Записать();
				КонецЕсли;
			Исключение
				БылиИсключения = Истина;
				ИнформацияОбОшибке = ИнформацияОбОшибке();
				ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'При записи объекта ""%1"" возникла ошибка:
					           |%2'"),
					ПолучитьНавигационнуюСсылку(Параметры.Объект.Ссылка),
					ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
				Если ТранзакцияАктивна() Тогда
					ВызватьИсключение ТекстОшибки;
				КонецЕсли;
				СообщитьОбОшибке(ТекстОшибки, ОбъектыРасширений);
			КонецПопытки;
		КонецЕсли;
		
	Исключение
		БылиИсключения = Истина;
		ВызватьИсключение;
	КонецПопытки;
	
	Возврат Не БылиИсключения;
	// АПК:1327-вкл.
	
КонецФункции

// Возвращаемое значение:
//  Структура:
//   * Объект - СправочникОбъект 
//            - Неопределено
// 
Функция ПараметрыЗаменыЭлементов()
	
	Параметры = Новый Структура;
	Параметры.Вставить("Объект", Неопределено);
	Возврат Параметры;
	
КонецФункции


// Процедура из универсальной обработки ПоискИЗаменаЗначений.
// Изменения:
// - заменен метод Сообщить(...) на ЗаписьЖурналаРегистрации(...).
//
Процедура СообщитьОбОшибке(Знач Описание, ОбъектыРасширений)
	
	ЗаписьЖурналаРегистрации(
		?(ОбъектыРасширений,
			НСтр("ru = 'Идентификаторы объектов расширений.Замена идентификатора'",
				ОбщегоНазначения.КодОсновногоЯзыка()),
			НСтр("ru = 'Идентификаторы объектов метаданных.Замена идентификатора'",
				ОбщегоНазначения.КодОсновногоЯзыка())),
		УровеньЖурналаРегистрации.Ошибка,
		,
		,
		Описание,
		РежимТранзакцииЗаписиЖурналаРегистрации.Независимая);
	
КонецПроцедуры

#КонецОбласти

#КонецЕсли

#КонецЕсли